diff options
Diffstat (limited to 'src/VBox/Frontends/VBoxManage')
36 files changed, 65235 insertions, 0 deletions
diff --git a/src/VBox/Frontends/VBoxManage/.scm-settings b/src/VBox/Frontends/VBoxManage/.scm-settings new file mode 100644 index 00000000..014df96e --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/.scm-settings @@ -0,0 +1,29 @@ +# $Id: .scm-settings $ +## @file +# Source code massager settings for VBoxManage. +# + +# +# Copyright (C) 2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +/*: --no-rc-use + diff --git a/src/VBox/Frontends/VBoxManage/Makefile.kmk b/src/VBox/Frontends/VBoxManage/Makefile.kmk new file mode 100644 index 00000000..2a63da42 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/Makefile.kmk @@ -0,0 +1,413 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for VBoxManage (the CLI frontend). +# + +# +# Copyright (C) 2006-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +SUB_DEPTH = ../../../.. +include $(KBUILD_PATH)/subheader.kmk + +include $(PATH_ROOT)/doc/manual/Config.kmk + + +## @todo r=andy Sort this stuff alphabetically! +VBOX_COMMON_VBOXMANAGE_DEFS = \ + $(if $(VBOX_WITH_AHCI), VBOX_WITH_AHCI) \ + $(if $(VBOX_WITH_COPYTOGUEST),VBOX_WITH_COPYTOGUEST) \ + $(if $(VBOX_WITH_E1000),VBOX_WITH_E1000) \ + $(if $(VBOX_WITH_GUEST_CONTROL),VBOX_WITH_GUEST_CONTROL) \ + $(if $(VBOX_WITH_GUEST_PROPS),VBOX_WITH_GUEST_PROPS) \ + $(if $(VBOX_WITH_HEADLESS), VBOX_WITH_HEADLESS) \ + $(if $(VBOX_WITH_HGCM), VBOX_WITH_HGCM) \ + $(if $(VBOX_WITH_HOSTNETIF_API), VBOX_WITH_HOSTNETIF_API) \ + $(if $(VBOX_WITH_NETFLT), VBOX_WITH_NETFLT) \ + $(if-expr defined(VBOX_WITH_VMNET) && "$(KBUILD_TARGET)"=="darwin",VBOX_WITH_VMNET,) \ + $(if $(VBOX_WITH_CLOUD_NET), VBOX_WITH_CLOUD_NET) \ + $(if $(VBOX_WITH_AUDIO_OSS), VBOX_WITH_AUDIO_OSS) \ + $(if $(VBOX_WITH_AUDIO_ALSA), VBOX_WITH_AUDIO_ALSA) \ + $(if $(VBOX_WITH_AUDIO_PULSE),VBOX_WITH_AUDIO_PULSE) \ + $(if $(VBOX_WITH_SCSI), VBOX_WITH_SCSI) \ + $(if $(VBOX_WITH_VBOXSDL), VBOX_WITH_VBOXSDL) \ + $(if $(VBOX_WITH_VIDEOHWACCEL), VBOX_WITH_VIDEOHWACCEL) \ + $(if $(VBOX_WITH_VIRTIO),VBOX_WITH_VIRTIO) \ + $(if $(VBOX_WITH_VIRTIO_NET_1_0),VBOX_WITH_VIRTIO_NET_1_0) \ + $(if $(VBOX_WITH_USB_CARDREADER),VBOX_WITH_USB_CARDREADER) \ + $(if $(VBOX_WITH_PCI_PASSTHROUGH),VBOX_WITH_PCI_PASSTHROUGH) \ + $(if $(VBOX_WITH_RECORDING),VBOX_WITH_RECORDING) \ + $(if $(VBOX_WITH_AUDIO_RECORDING),VBOX_WITH_AUDIO_RECORDING) \ + $(if $(VBOX_WITH_NAT_SERVICE),VBOX_WITH_NAT_SERVICE) \ + $(if $(VBOX_WITH_SHARED_CLIPBOARD),VBOX_WITH_SHARED_CLIPBOARD) \ + $(if $(VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS),VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS) \ + $(if $(VBOX_WITH_IOMMU_AMD),VBOX_WITH_IOMMU_AMD) \ + $(if $(VBOX_WITH_IOMMU_INTEL),VBOX_WITH_IOMMU_INTEL) \ + $(if $(VBOX_WITH_UPDATE_AGENT), VBOX_WITH_UPDATE_AGENT) \ + $(if $(VBOX_WITH_VMSVGA),VBOX_WITH_VMSVGA) \ + $(if $(VBOX_WITH_MAIN_NLS),VBOX_WITH_MAIN_NLS) \ + $(if $(VBOX_WITH_TPM),VBOX_WITH_TPM) \ + $(if $(VBOX_WITH_FULL_VM_ENCRYPTION),VBOX_WITH_FULL_VM_ENCRYPTION) + + +ifndef VBOX_ONLY_DOCS + PROGRAMS += VBoxManage + VBoxManage_TEMPLATE = VBoxMainClientExe + VBoxManage_DEFS += $(VBOX_COMMON_VBOXMANAGE_DEFS) + VBoxManage_DEFS.win = _WIN32_WINNT=0x0500 + VBoxManage_INCS = \ + $(VBoxManage_0_OUTDIR) \ + ../Common + VBoxManage_INTERMEDIATES = \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h + VBoxManage_SOURCES = \ + VBoxManage.cpp \ + VBoxManageUtils.cpp \ + VBoxInternalManage.cpp \ + VBoxManageAppliance.cpp \ + VBoxManageBandwidthControl.cpp \ + VBoxManageControlVM.cpp \ + VBoxManageDebugVM.cpp \ + VBoxManageDHCPServer.cpp \ + VBoxManageDisk.cpp \ + $(if $(VBOX_WITH_GUEST_CONTROL),VBoxManageGuestCtrl.cpp) \ + $(if $(VBOX_WITH_GUEST_CONTROL),VBoxManageGuestCtrlListener.cpp) \ + $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \ + VBoxManageHelp.cpp \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_en_US.cpp \ + VBoxManageHostonly.cpp \ + VBoxManageInfo.cpp \ + VBoxManageList.cpp \ + VBoxManageMetrics.cpp \ + VBoxManageMisc.cpp \ + VBoxManageModifyVM.cpp \ + VBoxManageModifyNvram.cpp \ + VBoxManageSnapshot.cpp \ + VBoxManageStorageController.cpp \ + $(if $(VBOX_WITH_UPDATE_AGENT),VBoxManageUpdateCheck.cpp) \ + VBoxManageUSB.cpp \ + $(if $(VBOX_WITH_NAT_SERVICE),VBoxManageNATNetwork.cpp,) \ + $(if $(VBOX_WITH_NAT_SERVICE),../../NetworkServices/NetLib/VBoxNetPortForwardString.cpp,) \ + VBoxManageCloud.cpp \ + VBoxManageCloudMachine.cpp \ + ../Common/PasswordInput.cpp + VBoxManage_SOURCES.win = \ + VBoxManage.rc + VBoxManage_LIBS += $(LIB_DDU) + + ifdef VBOX_WITH_VBOXMANAGE_NLS + VBOX_PATH_VBOXMANAGE_SRC := $(PATH_SUB_CURRENT) + include $(PATH_SUB_CURRENT)/nls/ApprovedLanguages.kmk + + VBoxManage_DEFS += VBOX_WITH_VBOXMANAGE_NLS + VBoxManage_INCS += \ + $(PATH_ROOT)/src/VBox/Main/include + VBoxManage_SOURCES += \ + $(PATH_ROOT)/src/VBox/Main/src-all/VirtualBoxTranslator.cpp \ + $(PATH_ROOT)/src/VBox/Main/src-all/QMTranslatorImpl.cpp \ + $(PATH_ROOT)/src/VBox/Main/src-all/GlobalStatusConversion.cpp + + # $(addsuffix /VBoxManageBuiltInHelp.cpp,$(addprefix $(VBoxManage_0_OUTDIR)/,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES))) + #VBoxManage_INTERMEDIATES += \ + # $(addsuffix /VBoxManageBuiltInHelp.h,$(addprefix $(VBoxManage_0_OUTDIR)/,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES))) + + # define qt5 tools for translation + USES += qt5 + + PROGRAMS += VBoxManageNls + VBoxManageNls_TEMPLATE = VBoxNLS + VBoxManageNls_QT_TRANSLATIONS = $(addsuffix .ts,$(addprefix $(VBOX_PATH_VBOXMANAGE_SRC)/nls/VBoxManageNls_,$(VBOX_APPROVED_VBOXMANAGE_LANGUAGES))) + VBoxManageNls_VBOX_ALL_NLS_SOURCES = $(wildcard \ + $(VBOX_PATH_VBOXMANAGE_SRC)/*.h \ + $(VBOX_PATH_VBOXMANAGE_SRC)/*.cpp ) + + updatenls:: makeallnls $(VBOX_PATH_VBOXMANAGE_SRC)/nls/VBoxManageNls_en.ts + + makeallnls:: $(VBoxManageNls_VBOX_ALL_NLS_SOURCES) + $(call MSG_L1,lupdate all languages (nls/*.ts)) + $(QUIET)$(TOOL_QT5_LUPDATE) \ + $^ \ + -ts \ + $(filter-out nls/VBoxManageNls_en.ts, $(VBoxManageNls_QT_TRANSLATIONS)) \ + $(VBOX_PATH_VBOXMANAGE_SRC)/nls/VBoxManageNls_xx_YY.ts + + # fake-main-nls: + # $(foreach file, $(VBoxManageNls_QT_TRANSLATIONS) \ + # ,$(NLTAB)$(SED) -i \ + # -e '/<source>.*<\/source>/h' \ + # -e '/<source>.*<\/source>/p' \ + # -e '/<translation type="unfinished"><\/translation>/{' \ + # -e 'x' \ + # -e 's/<source>\(.*\)<\/source>/<translation type="unfinished">$(notdir $(file)): \1<\/translation>/' \ + # -e '}' \ + # $(file) ) + + + # Create the English translation file. This is something special cause it will + # contain the plural forms only. + $(VBOX_PATH_VBOXMANAGE_SRC)/nls/VBoxManageNls_en.ts: $(VBoxManageNls_VBOX_ALL_NLS_SOURCES) + $(call MSG_L1,lupdate $@) + $(QUIET)$(TOOL_QT5_LUPDATE) \ + $^ \ + -ts \ + "$@" + $(QUIET)$(SED) -n -i \ + -e '/<context>/,/<\/context>/!p' \ + -e '/<context>/h' \ + -e '/<name>/H' \ + -e '/<message numerus="yes">/,/<\/message>/H' \ + -e '/<\/context>/{H;x;/<message/p}' \ + "$@" + + endif # VBOX_WITH_VBOXMANAGE_NLS + + + # VBoxNetPortForwardString.h + VBoxManageNATNetwork.cpp_INCS += ../../NetworkServices/NetLib/ + +endif # VBOX_ONLY_DOCS + +ifneq ($(KBUILD_TARGET),win) + # Workaround for buggy gcc-4.3 compilers, see + # + # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36474 + # + # Some later revisions of version 4.3.1 are known to work so we assume + # that version 4.3.2 or later has this bug definitely fixed. + VBoxManage_CXXFLAGS.release += \ + $(if $(VBOX_GCC_VERSION_CXX),$(if-expr $(VBOX_GCC_VERSION_CXX) < 40300 || $(VBOX_GCC_VERSION_CXX) > 40301,,--param max-fields-for-field-sensitive=0),) + VBoxManageHelp_CXXFLAGS.release = $(VBoxManage_CXXFLAGS.release) +endif + + +# +# VBoxManage built-in help from XML refentry in doc/manual/en_US/. +# +$(call KB_FN_DO_PASS0_ON_TARGET,VBoxManage) + +VBoxManage_CLEAN += \ + $(VBOX_XML_CATALOG) \ + $(VBOX_XML_CATALOG_DOCBOOK) \ + $(VBOX_XML_CATALOG_MANUAL) \ + $(VBOX_XML_ENTITIES) \ + $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/en_US/, $(VBOX_XML_XREF_TO_TEXT) $(VBOX_XML_XREF_TO_TEXT).cat) \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_en_US.cpp \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_en_US.cpp.ts \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp.ts \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h.ts \ + $(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) + +# Preprocess the xml files, applying remarks. +$(foreach file,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \ +, $(evalcall2 def_vbox_refentry_preprocess_for_manpage,$(VBoxManage_0_OUTDIR),$(file), \ + $(VBOX_PATH_MANUAL_SRC)/en_US/$(file),replace-xrefs,en_US)) + + +## +# Emits rules for generating cpp files from man pages. +# +# $(evalcall2 def_vbox_man_generate_cpp_help) +# @param 1 Folder with preprocessed man_VBoxManage_* files +# @param 2 language code. +define def_vbox_man_generate_cpp_help + ifneq ($(2),en_US) + VBOX_DOCBOOK_REFENTRY_TO_C_HELP_$(2) = $(VBOX_PATH_MANUAL_SRC)/$(2)/docbook-refentry-to-C-help.xsl + else + VBOX_DOCBOOK_REFENTRY_TO_C_HELP_$(2) = $(VBOX_DOCBOOK_REFENTRY_TO_C_HELP) + endif + $$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_$(2).cpp.ts \ + +| $$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_$(2).cpp: \ + $$(VBOX_DOCBOOK_REFENTRY_TO_C_HELP_$(2)) \ + $$(VBOX_DOCBOOK_REFENTRY_TO_C_HELP) \ + $$(addprefix $(1)/,$$(filter man_VBoxManage-%,$$(VBOX_MANUAL_XML_REFENTRY_FILES))) \ + $$(VBOX_XML_CATALOG) $$(VBOX_XML_CATALOG_DOCBOOK) $$(MAKEFILE) | $$$$(dir $$$$@) + $$(call MSG_TOOL,xsltproc $$(notdir $$(firstword $$(filter %.xsl,$$^))),,$$(filter %.xml,$$^),$$(patsubst %.ts,%,$$@)) + $$(QUIET)$$(APPEND) -tn "$$@" \ + '/* Autogenerated by $$<, do not edit! */' \ + '' \ + '#include "VBoxManageBuiltInHelp.h"' \ + '' \ + 'RT_C_DECLS_BEGIN' \ + '/* make next variables visible outside the module */' \ + 'extern PCRTMSGREFENTRY g_apHelpEntries_$(2)[];' \ + 'extern const uint32_t g_cHelpEntries_$(2);' \ + 'RT_C_DECLS_END' \ + '' \ + $$(foreach refentry,$$(filter %.xml,$$^) \ + ,$$(NLTAB)$$(QUIET)$$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$$@") \ + --path '$(VBOX_PATH_MANUAL_SRC)/$(2) $(VBOX_PATH_MANUAL_SRC)/en_US' $$< $$(refentry)) + $$(QUIET)$$(APPEND) -n "$$@" \ + '' \ + 'PCRTMSGREFENTRY g_apHelpEntries_$(2)[] =' \ + '{' + $$(foreach refentry,$$(filter %.xml,$$^) \ + ,$$(NLTAB)$$(QUIET)$$(APPEND) -n "$$@" \ + ' &g_$$(subst -,_,$$(tolower $$(patsubst man_%,%,$$(notdir $$(basename $$(refentry)))))),') + $$(QUIET)$$(APPEND) -n "$$@" \ + '};' \ + '' \ + 'const uint32_t g_cHelpEntries_$(2) = RT_ELEMENTS(g_apHelpEntries_$(2));' \ + '' + $$(QUIET)$$(CP) --changed -- "$$@" "$$(patsubst %.ts,%,$$@)" +endef +# The above APPEND stuff trigger some kind of problem on some boxes when not split up... +# update: Fixed in SVN (strcpy -> memmove in new_job(), job.c - r2591). Just need to rebuild all platforms. + +# Generate the .cpp file. +$(evalcall2 def_vbox_man_generate_cpp_help, $(VBoxManage_0_OUTDIR),en_US) + + +# Generate built-in help for all languages (English is implicit). +$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp.ts \ ++| $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.cpp: \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_en_US.cpp \ + $(foreach lang,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES), $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_$(lang).cpp ) \ + $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h + $(QUIET)$(APPEND) -tn "$@" \ + '/* Autogenerated, do not edit! */' \ + '' \ + '#include "VBoxManageBuiltInHelp.h"' \ + '' \ + 'RT_C_DECLS_BEGIN' \ + '' \ + 'extern PCRTMSGREFENTRY g_apHelpEntries_en_US[];' \ + 'extern const uint32_t g_cHelpEntries_en_US;' +ifdef VBOX_WITH_VBOXMANAGE_NLS + $(foreach lang,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES) \ + ,$(NLTAB)$(QUIET)$(APPEND) -n "$@" \ + '' \ + 'extern PCRTMSGREFENTRY g_apHelpEntries_$(lang)[];' \ + 'extern const uint32_t g_cHelpEntries_$(lang);') +endif + $(QUIET)$(APPEND) -n "$@" \ + '' \ + 'RT_C_DECLS_END' \ + '' \ + 'HELP_LANG_ENTRY_T const g_aHelpLangEntries[] = ' \ + '{' \ + ' { "en_US", 5, &g_apHelpEntries_en_US[0], &g_cHelpEntries_en_US },' +ifdef VBOX_WITH_VBOXMANAGE_NLS + $(foreach lang,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES) \ + ,$(NLTAB)$(QUIET)$(APPEND) "$@" ' { "$(lang)", $(length $(lang)), &g_apHelpEntries_$(lang)[0], &g_cHelpEntries_$(lang) },' ) +endif + $(QUIET)$(APPEND) -n "$@" \ + '};' \ + '' \ + 'uint32_t const g_cHelpLangEntries = RT_ELEMENTS(g_aHelpLangEntries);' \ + '' \ + 'PCHELP_LANG_ENTRY_T volatile g_pHelpLangEntry = &g_aHelpLangEntries[0];'\ + '' + $(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)" + + +$(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h.ts \ ++| $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp.h: \ + $(VBOX_DOCBOOK_REFENTRY_TO_H_HELP) \ + $(addprefix $(VBoxManage_0_OUTDIR)/,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES))) \ + $(VBOX_XML_CATALOG) $(VBOX_XML_CATALOG_DOCBOOK) $(MAKEFILE) | $$(dir $$@) + $(call MSG_TOOL,xsltproc $(notdir $(firstword $(filter %.xsl,$^))),,$(filter %.xml,$^),$(patsubst %.ts,%,$@)) + $(QUIET)$(APPEND) -tn "$@" \ + '/* Autogenerated by $<, do not edit! */' \ + '' \ + '#ifndef ___VBoxManageBuiltInHelp_h___' \ + '#define ___VBoxManageBuiltInHelp_h___' \ + '' \ + '#include <iprt/message.h>' \ + '#include <iprt/assertcompile.h>' \ + '' \ + 'RT_C_DECLS_BEGIN' \ + '' \ + 'typedef enum HELP_CMD_VBOXMANAGE' \ + '{' \ + ' HELP_CMD_VBOXMANAGE_INVALID = 0,' + $(foreach refentry,$(filter %.xml,$^) \ + ,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \ + --stringparam 'g_sMode' 'cmd' $< $(refentry)) + $(QUIET)$(APPEND) -n "$@" \ + ' HELP_CMD_VBOXMANAGE_END' \ + '} HELP_CMD_VBOXMANAGE;' + $(foreach refentry,$(filter %.xml,$^) \ + ,$(NLTAB)$(QUIET)$(call VBOX_XSLTPROC_WITH_CAT, -a+to "$@") \ + --stringparam 'g_sMode' 'subcmd' $< $(refentry)) + $(QUIET)$(APPEND) -n "$@" \ + '' \ + 'typedef struct HELP_LANG_ENTRY_T' \ + '{' \ + ' const char *pszLang;' \ + ' size_t cchLang;' \ + ' PCRTMSGREFENTRY *papHelpEntries;' \ + ' uint32_t const *pcHelpEntries;' \ + '} HELP_LANG_ENTRY_T;' \ + 'typedef HELP_LANG_ENTRY_T const *PCHELP_LANG_ENTRY_T;' \ + '' \ + 'extern HELP_LANG_ENTRY_T const g_aHelpLangEntries[];' \ + 'extern const uint32_t g_cHelpLangEntries;' \ + '' \ + 'extern PCHELP_LANG_ENTRY_T volatile g_pHelpLangEntry;' \ + '' \ + 'RT_C_DECLS_END' \ + '' \ + '#endif' \ + '' + $(QUIET)$(CP) --changed -- "$@" "$(patsubst %.ts,%,$@)" + +ifdef VBOX_WITH_VBOXMANAGE_NLS + VBoxManage_BLDDIRS += \ + $(addprefix $(VBoxManage_0_OUTDIR)/,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES)) + + VBoxManage_SOURCES += \ + $(foreach lang, $(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES) \ + , $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_$(lang).cpp) + + VBoxManage_CLEAN += \ + $(foreach lang,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES), \ + $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/, \ + $(VBOX_XML_XREF_TO_TEXT) \ + $(VBOX_XML_XREF_TO_TEXT).cat \ + )) \ + $(addsuffix .cpp,$(addprefix $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES))) \ + $(addsuffix .cpp.ts,$(addprefix $(VBoxManage_0_OUTDIR)/VBoxManageBuiltInHelp_,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES))) \ + $(foreach file, $(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \ + , $(addsuffix /$(file),$(addprefix $(VBoxManage_0_OUTDIR)/,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES)))) + + # Preprocess the xml files, applying remarks. + $(foreach lang, $(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES) \ + , $(foreach file,$(filter man_VBoxManage-%,$(VBOX_MANUAL_XML_REFENTRY_FILES)) \ + , $(evalcall2 def_vbox_refentry_preprocess_for_manpage,$(VBoxManage_0_OUTDIR)/$(lang),$(file) \ + ,$(VBOX_PATH_MANUAL_SRC)/$(lang)/$(file),replace-xrefs,$(lang)))) + + # Generate the .cpp file. + $(foreach lang, $(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES) \ + , $(evalcall2 def_vbox_man_generate_cpp_help,$(VBoxManage_0_OUTDIR)/$(lang),$(lang))) + + # Ensure $(lang) subfolder in the $(VBOX_PATH_MANUAL_OUTBASE) is created (for section names file) + BLDDIRS += $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/,$(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES)) + + # Generate sections names file for $(lang) + $(foreach lang, $(VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES) \ + , $(evalcall2 def_vbox_xref_to_text,$(lang))) + +endif + +include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp b/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp new file mode 100644 index 00000000..f290fb57 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp @@ -0,0 +1,2114 @@ +/* $Id: VBoxInternalManage.cpp $ */ +/** @file + * VBoxManage - The 'internalcommands' command. + * + * VBoxInternalManage used to be a second CLI for doing special tricks, + * not intended for general usage, only for assisting VBox developers. + * It is now integrated into VBoxManage. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> + +#include <VBox/com/VirtualBox.h> + +#include <VBox/vd.h> +#include <VBox/sup.h> +#include <VBox/log.h> +#include <VBox/version.h> + +#include <iprt/buildconfig.h> +#include <iprt/ctype.h> +#include <iprt/file.h> +#include <iprt/getopt.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/uuid.h> +#include <iprt/sha.h> + +#include "VBoxManage.h" + +/* Includes for the raw disk stuff. */ +#ifdef RT_OS_WINDOWS +# include <iprt/win/windows.h> +# include <winioctl.h> +#elif defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) \ + || defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) +# include <errno.h> +# include <sys/ioctl.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <fcntl.h> +# include <unistd.h> +#endif +#ifdef RT_OS_LINUX +# include <sys/utsname.h> +# include <linux/hdreg.h> +# include <linux/fs.h> +# include <stdlib.h> /* atoi() */ +#endif /* RT_OS_LINUX */ +#ifdef RT_OS_DARWIN +# include <sys/disk.h> +#endif /* RT_OS_DARWIN */ +#ifdef RT_OS_SOLARIS +# include <stropts.h> +# include <sys/dkio.h> +# include <sys/vtoc.h> +#endif /* RT_OS_SOLARIS */ +#ifdef RT_OS_FREEBSD +# include <sys/disk.h> +#endif /* RT_OS_FREEBSD */ + +using namespace com; + + +/** Macro for checking whether a partition is of extended type or not. */ +#define PARTTYPE_IS_EXTENDED(x) ((x) == 0x05 || (x) == 0x0f || (x) == 0x85) + +/** Maximum number of partitions we can deal with. + * Ridiculously large number, but the memory consumption is rather low so who + * cares about never using most entries. */ +#define HOSTPARTITION_MAX 100 + +DECLARE_TRANSLATION_CONTEXT(Internal); + + +typedef struct HOSTPARTITION +{ + /** partition number */ + unsigned uIndex; + /** partition number (internal only, windows specific numbering) */ + unsigned uIndexWin; + /** partition type */ + unsigned uType; + /** CHS/cylinder of the first sector */ + unsigned uStartCylinder; + /** CHS/head of the first sector */ + unsigned uStartHead; + /** CHS/head of the first sector */ + unsigned uStartSector; + /** CHS/cylinder of the last sector */ + unsigned uEndCylinder; + /** CHS/head of the last sector */ + unsigned uEndHead; + /** CHS/sector of the last sector */ + unsigned uEndSector; + /** start sector of this partition relative to the beginning of the hard + * disk or relative to the beginning of the extended partition table */ + uint64_t uStart; + /** numer of sectors of the partition */ + uint64_t uSize; + /** start sector of this partition _table_ */ + uint64_t uPartDataStart; + /** numer of sectors of this partition _table_ */ + uint64_t cPartDataSectors; +} HOSTPARTITION, *PHOSTPARTITION; + +typedef struct HOSTPARTITIONS +{ + /** partitioning type - MBR or GPT */ + VDISKPARTTYPE uPartitioningType; + unsigned cPartitions; + HOSTPARTITION aPartitions[HOSTPARTITION_MAX]; +} HOSTPARTITIONS, *PHOSTPARTITIONS; + + +/** @name Syntax diagram category, i.e. the command. + * @{ */ +typedef enum +{ + USAGE_INVALID = 0, + USAGE_I_LOADSYMS, + USAGE_I_LOADMAP, + USAGE_I_SETHDUUID, + USAGE_I_LISTPARTITIONS, + USAGE_I_CREATERAWVMDK, + USAGE_I_MODINSTALL, + USAGE_I_MODUNINSTALL, + USAGE_I_RENAMEVMDK, + USAGE_I_CONVERTTORAW, + USAGE_I_CONVERTHD, + USAGE_I_DUMPHDINFO, + USAGE_I_DEBUGLOG, + USAGE_I_SETHDPARENTUUID, + USAGE_I_PASSWORDHASH, + USAGE_I_GUESTSTATS, + USAGE_I_REPAIRHD, + USAGE_I_ALL +} USAGECATEGORY; +/** @} */ + + +/** + * Print the usage info. + */ +static void printUsageInternal(USAGECATEGORY enmCommand, PRTSTREAM pStrm) +{ + Assert(enmCommand != USAGE_INVALID); + RTStrmPrintf(pStrm, + Internal::tr( + "Usage: VBoxManage internalcommands <command> [command arguments]\n" + "\n" + "Commands:\n" + "\n" + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" + "WARNING: This is a development tool and should only be used to analyse\n" + " problems. It is completely unsupported and will change in\n" + " incompatible ways without warning.\n"), + + (enmCommand == USAGE_I_LOADMAP || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " loadmap <vmname|uuid> <symfile> <address> [module] [subtrahend] [segment]\n" + " This will instruct DBGF to load the given map file\n" + " during initialization. (See also loadmap in the debugger.)\n" + "\n") + : "", + (enmCommand == USAGE_I_LOADSYMS || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " loadsyms <vmname|uuid> <symfile> [delta] [module] [module address]\n" + " This will instruct DBGF to load the given symbol file\n" + " during initialization.\n" + "\n") + : "", + (enmCommand == USAGE_I_SETHDUUID || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " sethduuid <filepath> [<uuid>]\n" + " Assigns a new UUID to the given image file. This way, multiple copies\n" + " of a container can be registered.\n" + "\n") + : "", + (enmCommand == USAGE_I_SETHDPARENTUUID || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " sethdparentuuid <filepath> <uuid>\n" + " Assigns a new parent UUID to the given image file.\n" + "\n") + : "", + (enmCommand == USAGE_I_DUMPHDINFO || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " dumphdinfo <filepath>\n" + " Prints information about the image at the given location.\n" + "\n") + : "", + (enmCommand == USAGE_I_LISTPARTITIONS || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " listpartitions -rawdisk <diskname>\n" + " Lists all partitions on <diskname>.\n" + "\n") + : "", + (enmCommand == USAGE_I_CREATERAWVMDK || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " createrawvmdk --filename <filename> --rawdisk <diskname>\n" + " [--partitions <list of partition numbers> [--mbr <filename>] ]\n" + " [--relative]\n" + " Creates a new VMDK image which gives direct access to a physical hard\n" + " disk on the host. The entire disk can be presented to the guest or\n" + " just specific partitions specified using the --partitions parameter.\n" + " If access to individual partitions is granted, then the --mbr parameter\n" + " can be used to specify an alternative Master Boot Record (MBR) (note\n" + " that the partitioning information in the MBR file is ignored). The\n" + " format of the diskname argument for the --rawdisk parameter varies by\n" + " platform but can be determined using the command:\n" + " VBoxManage list hostdrives\n" + " The output lists the available drives and their partitions along with\n" + " their partition types and sizes.\n" + " On Linux, FreeBSD, and Windows hosts the --relative parameter creates a\n" + " VMDK image file which references the specified individual partitions\n" + " directly instead of referencing the partitions by their offset from\n" + " the start of the physical disk.\n" + "\n" + " Nota Bene: The 'createrawvdk' subcommand is deprecated. The equivalent\n" + " functionality is available using the 'VBoxManage createmedium' command\n" + " and should be used instead. See 'VBoxManage help createmedium' for\n" + " details.\n" + "\n") + : "", + (enmCommand == USAGE_I_RENAMEVMDK || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " renamevmdk -from <filename> -to <filename>\n" + " Renames an existing VMDK image, including the base file and all its extents.\n" + "\n") + : "", + (enmCommand == USAGE_I_CONVERTTORAW || enmCommand == USAGE_I_ALL) +#ifdef ENABLE_CONVERT_RAW_TO_STDOUT + ? Internal::tr( + " converttoraw [-format <fileformat>] <filename> <outputfile>|stdout" + "\n" + " Convert image to raw, writing to file or stdout.\n" + "\n") +#else + ? Internal::tr( + " converttoraw [-format <fileformat>] <filename> <outputfile>" + "\n" + " Convert image to raw, writing to file.\n" + "\n") +#endif + : "", + (enmCommand == USAGE_I_CONVERTHD || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " converthd [-srcformat VDI|VMDK|VHD|RAW]\n" + " [-dstformat VDI|VMDK|VHD|RAW]\n" + " <inputfile> <outputfile>\n" + " converts hard disk images between formats\n" + "\n") + : "", + (enmCommand == USAGE_I_REPAIRHD || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " repairhd [-dry-run]\n" + " [-format VDI|VMDK|VHD|...]\n" + " <filename>\n" + " Tries to repair corrupted disk images\n" + "\n") + : "", +#ifdef RT_OS_WINDOWS + (enmCommand == USAGE_I_MODINSTALL || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " modinstall\n" + " Installs the necessary driver for the host OS\n" + "\n") + : "", + (enmCommand == USAGE_I_MODUNINSTALL || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " moduninstall\n" + " Deinstalls the driver\n" + "\n") + : "", +#else + "", + "", +#endif + (enmCommand == USAGE_I_DEBUGLOG || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " debuglog <vmname|uuid> [--enable|--disable] [--flags todo]\n" + " [--groups todo] [--destinations todo]\n" + " Controls debug logging.\n" + "\n") + : "", + (enmCommand == USAGE_I_PASSWORDHASH || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " passwordhash <password>\n" + " Generates a password hash.\n" + "\n") + : "", + (enmCommand == USAGE_I_GUESTSTATS || enmCommand == USAGE_I_ALL) + ? Internal::tr( + " gueststats <vmname|uuid> [--interval <seconds>]\n" + " Obtains and prints internal guest statistics.\n" + " Sets the update interval if specified.\n" + "\n") + : "" + ); +} + + +/** + * Print a usage synopsis and the syntax error message. + * @returns RTEXITCODE_SYNTAX. + */ +static RTEXITCODE errorSyntaxInternal(USAGECATEGORY enmCommand, const char *pszFormat, ...) +{ + va_list args; + showLogo(g_pStdErr); // show logo even if suppressed + + printUsageInternal(enmCommand, g_pStdErr); + + va_start(args, pszFormat); + RTStrmPrintf(g_pStdErr, Internal::tr("\nSyntax error: %N\n"), pszFormat, &args); + va_end(args); + return RTEXITCODE_SYNTAX; +} + + +/** + * errorSyntaxInternal for RTGetOpt users. + * + * @returns RTEXITCODE_SYNTAX. + * + * @param enmCommand The command. + * @param vrc The RTGetOpt return code. + * @param pValueUnion The value union. + */ +static RTEXITCODE errorGetOptInternal(USAGECATEGORY enmCommand, int vrc, union RTGETOPTUNION const *pValueUnion) +{ + /* + * Check if it is an unhandled standard option. + */ + if (vrc == 'V') + { + RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision()); + return RTEXITCODE_SUCCESS; + } + + if (vrc == 'h') + { + showLogo(g_pStdErr); + printUsageInternal(enmCommand, g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + /* + * General failure. + */ + showLogo(g_pStdErr); // show logo even if suppressed + + printUsageInternal(enmCommand, g_pStdErr); + + if (vrc == VINF_GETOPT_NOT_OPTION) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Internal::tr("Invalid parameter '%s'"), pValueUnion->psz); + if (vrc > 0) + { + if (RT_C_IS_PRINT(vrc)) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Internal::tr("Invalid option -%c"), vrc); + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Internal::tr("Invalid option case %i"), vrc); + } + if (vrc == VERR_GETOPT_UNKNOWN_OPTION) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Internal::tr("Unknown option: %s"), pValueUnion->psz); + if (vrc == VERR_GETOPT_INVALID_ARGUMENT_FORMAT) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Internal::tr("Invalid argument format: %s"), pValueUnion->psz); + if (pValueUnion->pDef) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "%s: %Rrs", pValueUnion->pDef->pszLong, vrc); + return RTMsgErrorExit(RTEXITCODE_SYNTAX, "%Rrs", vrc); +} + + +/** + * Externally visible wrapper around printUsageInternal() to dump the + * complete usage text. + * + * @param pStrm The stream to dump the usage text to. + */ +DECLHIDDEN(void) printUsageInternalCmds(PRTSTREAM pStrm) +{ + printUsageInternal(USAGE_I_ALL, pStrm); +} + + +/** @todo this is no longer necessary, we can enumerate extra data */ +/** + * Finds a new unique key name. + * + * I don't think this is 100% race condition proof, but we assumes + * the user is not trying to push this point. + * + * @returns Result from the insert. + * @param pMachine The Machine object. + * @param pszKeyBase The base key. + * @param rKey Reference to the string object in which we will return the key. + */ +static HRESULT NewUniqueKey(ComPtr<IMachine> pMachine, const char *pszKeyBase, Utf8Str &rKey) +{ + Bstr KeyBase(pszKeyBase); + Bstr Keys; + HRESULT hrc = pMachine->GetExtraData(KeyBase.raw(), Keys.asOutParam()); + if (FAILED(hrc)) + return hrc; + + /* if there are no keys, it's simple. */ + if (Keys.isEmpty()) + { + rKey = "1"; + return pMachine->SetExtraData(KeyBase.raw(), Bstr(rKey).raw()); + } + + /* find a unique number - brute force rulez. */ + Utf8Str KeysUtf8(Keys); + const char *pszKeys = RTStrStripL(KeysUtf8.c_str()); + for (unsigned i = 1; i < 1000000; i++) + { + char szKey[32]; + size_t cchKey = RTStrPrintf(szKey, sizeof(szKey), "%#x", i); + const char *psz = strstr(pszKeys, szKey); + while (psz) + { + if ( ( psz == pszKeys + || psz[-1] == ' ') + && ( psz[cchKey] == ' ' + || !psz[cchKey]) + ) + break; + psz = strstr(psz + cchKey, szKey); + } + if (!psz) + { + rKey = szKey; + Utf8StrFmt NewKeysUtf8("%s %s", pszKeys, szKey); + return pMachine->SetExtraData(KeyBase.raw(), + Bstr(NewKeysUtf8).raw()); + } + } + RTMsgError(Internal::tr("Cannot find unique key for '%s'!"), pszKeyBase); + return E_FAIL; +} + + +#if 0 +/** + * Remove a key. + * + * I don't think this isn't 100% race condition proof, but we assumes + * the user is not trying to push this point. + * + * @returns Result from the insert. + * @param pMachine The machine object. + * @param pszKeyBase The base key. + * @param pszKey The key to remove. + */ +static HRESULT RemoveKey(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey) +{ + Bstr Keys; + HRESULT hrc = pMachine->GetExtraData(Bstr(pszKeyBase), Keys.asOutParam()); + if (FAILED(hrc)) + return hrc; + + /* if there are no keys, it's simple. */ + if (Keys.isEmpty()) + return S_OK; + + char *pszKeys; + int vrc = RTUtf16ToUtf8(Keys.raw(), &pszKeys); + if (RT_SUCCESS(vrc)) + { + /* locate it */ + size_t cchKey = strlen(pszKey); + char *psz = strstr(pszKeys, pszKey); + while (psz) + { + if ( ( psz == pszKeys + || psz[-1] == ' ') + && ( psz[cchKey] == ' ' + || !psz[cchKey]) + ) + break; + psz = strstr(psz + cchKey, pszKey); + } + if (psz) + { + /* remove it */ + char *pszNext = RTStrStripL(psz + cchKey); + if (*pszNext) + memmove(psz, pszNext, strlen(pszNext) + 1); + else + *psz = '\0'; + psz = RTStrStrip(pszKeys); + + /* update */ + hrc = pMachine->SetExtraData(Bstr(pszKeyBase), Bstr(psz)); + } + + RTStrFree(pszKeys); + return hrc; + } + else + RTMsgError(Internal::tr("Failed to delete key '%s' from '%s', string conversion error %Rrc!"), + pszKey, pszKeyBase, vrc); + + return E_FAIL; +} +#endif + + +/** + * Sets a key value, does necessary error bitching. + * + * @returns COM status code. + * @param pMachine The Machine object. + * @param pszKeyBase The key base. + * @param pszKey The key. + * @param pszAttribute The attribute name. + * @param pszValue The string value. + */ +static HRESULT SetString(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey, const char *pszAttribute, const char *pszValue) +{ + HRESULT hrc = pMachine->SetExtraData(BstrFmt("%s/%s/%s", pszKeyBase, + pszKey, pszAttribute).raw(), + Bstr(pszValue).raw()); + if (FAILED(hrc)) + RTMsgError(Internal::tr("Failed to set '%s/%s/%s' to '%s'! hrc=%#x"), + pszKeyBase, pszKey, pszAttribute, pszValue, hrc); + return hrc; +} + + +/** + * Sets a key value, does necessary error bitching. + * + * @returns COM status code. + * @param pMachine The Machine object. + * @param pszKeyBase The key base. + * @param pszKey The key. + * @param pszAttribute The attribute name. + * @param u64Value The value. + */ +static HRESULT SetUInt64(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey, const char *pszAttribute, uint64_t u64Value) +{ + char szValue[64]; + RTStrPrintf(szValue, sizeof(szValue), "%#RX64", u64Value); + return SetString(pMachine, pszKeyBase, pszKey, pszAttribute, szValue); +} + + +/** + * Sets a key value, does necessary error bitching. + * + * @returns COM status code. + * @param pMachine The Machine object. + * @param pszKeyBase The key base. + * @param pszKey The key. + * @param pszAttribute The attribute name. + * @param i64Value The value. + */ +static HRESULT SetInt64(ComPtr<IMachine> pMachine, const char *pszKeyBase, const char *pszKey, const char *pszAttribute, int64_t i64Value) +{ + char szValue[64]; + RTStrPrintf(szValue, sizeof(szValue), "%RI64", i64Value); + return SetString(pMachine, pszKeyBase, pszKey, pszAttribute, szValue); +} + + +/** + * Identical to the 'loadsyms' command. + */ +static RTEXITCODE CmdLoadSyms(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aSession); + HRESULT hrc; + + /* + * Get the VM + */ + ComPtr<IMachine> machine; + CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + + /* + * Parse the command. + */ + const char *pszFilename; + int64_t offDelta = 0; + const char *pszModule = NULL; + uint64_t ModuleAddress = UINT64_MAX; + uint64_t ModuleSize = 0; + + /* filename */ + if (argc < 2) + return errorArgument(Internal::tr("Missing the filename argument!\n")); + pszFilename = argv[1]; + + /* offDelta */ + if (argc >= 3) + { + int vrc = RTStrToInt64Ex(argv[2], NULL, 0, &offDelta); + if (RT_FAILURE(vrc)) + return errorArgument(argv[0], Internal::tr("Failed to read delta '%s', vrc=%Rrc\n"), argv[2], vrc); + } + + /* pszModule */ + if (argc >= 4) + pszModule = argv[3]; + + /* ModuleAddress */ + if (argc >= 5) + { + int vrc = RTStrToUInt64Ex(argv[4], NULL, 0, &ModuleAddress); + if (RT_FAILURE(vrc)) + return errorArgument(argv[0], Internal::tr("Failed to read module address '%s', vrc=%Rrc\n"), argv[4], vrc); + } + + /* ModuleSize */ + if (argc >= 6) + { + int vrc = RTStrToUInt64Ex(argv[5], NULL, 0, &ModuleSize); + if (RT_FAILURE(vrc)) + return errorArgument(argv[0], Internal::tr("Failed to read module size '%s', vrc=%Rrc\n"), argv[5], vrc); + } + + /* + * Add extra data. + */ + Utf8Str KeyStr; + hrc = NewUniqueKey(machine, "VBoxInternal/DBGF/loadsyms", KeyStr); + if (SUCCEEDED(hrc)) + hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "Filename", pszFilename); + if (SUCCEEDED(hrc) && argc >= 3) + hrc = SetInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "Delta", offDelta); + if (SUCCEEDED(hrc) && argc >= 4) + hrc = SetString(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "Module", pszModule); + if (SUCCEEDED(hrc) && argc >= 5) + hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "ModuleAddress", ModuleAddress); + if (SUCCEEDED(hrc) && argc >= 6) + hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadsyms", KeyStr.c_str(), "ModuleSize", ModuleSize); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/** + * Identical to the 'loadmap' command. + */ +static RTEXITCODE CmdLoadMap(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aSession); + HRESULT hrc; + + /* + * Get the VM + */ + ComPtr<IMachine> machine; + CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + + /* + * Parse the command. + */ + const char *pszFilename; + uint64_t ModuleAddress = UINT64_MAX; + const char *pszModule = NULL; + uint64_t offSubtrahend = 0; + uint32_t iSeg = UINT32_MAX; + + /* filename */ + if (argc < 2) + return errorArgument(Internal::tr("Missing the filename argument!\n")); + pszFilename = argv[1]; + + /* address */ + if (argc < 3) + return errorArgument(Internal::tr("Missing the module address argument!\n")); + int vrc = RTStrToUInt64Ex(argv[2], NULL, 0, &ModuleAddress); + if (RT_FAILURE(vrc)) + return errorArgument(argv[0], Internal::tr("Failed to read module address '%s', vrc=%Rrc\n"), argv[2], vrc); + + /* name (optional) */ + if (argc > 3) + pszModule = argv[3]; + + /* subtrahend (optional) */ + if (argc > 4) + { + vrc = RTStrToUInt64Ex(argv[4], NULL, 0, &offSubtrahend); + if (RT_FAILURE(vrc)) + return errorArgument(argv[0], Internal::tr("Failed to read subtrahend '%s', vrc=%Rrc\n"), argv[4], vrc); + } + + /* segment (optional) */ + if (argc > 5) + { + vrc = RTStrToUInt32Ex(argv[5], NULL, 0, &iSeg); + if (RT_FAILURE(vrc)) + return errorArgument(argv[0], Internal::tr("Failed to read segment number '%s', vrc=%Rrc\n"), argv[5], vrc); + } + + /* + * Add extra data. + */ + Utf8Str KeyStr; + hrc = NewUniqueKey(machine, "VBoxInternal/DBGF/loadmap", KeyStr); + if (SUCCEEDED(hrc)) + hrc = SetString(machine, "VBoxInternal/DBGF/loadmap", KeyStr.c_str(), "Filename", pszFilename); + if (SUCCEEDED(hrc)) + hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadmap", KeyStr.c_str(), "Address", ModuleAddress); + if (SUCCEEDED(hrc) && pszModule != NULL) + hrc = SetString(machine, "VBoxInternal/DBGF/loadmap", KeyStr.c_str(), "Name", pszModule); + if (SUCCEEDED(hrc) && offSubtrahend != 0) + hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadmap", KeyStr.c_str(), "Subtrahend", offSubtrahend); + if (SUCCEEDED(hrc) && iSeg != UINT32_MAX) + hrc = SetUInt64(machine, "VBoxInternal/DBGF/loadmap", KeyStr.c_str(), "Segment", iSeg); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static DECLCALLBACK(void) handleVDError(void *pvUser, int vrc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) +{ + RT_NOREF(pvUser); + RTMsgErrorV(pszFormat, va); + RTMsgError(Internal::tr("Error code %Rrc at %s(%u) in function %s"), vrc, RT_SRC_POS_ARGS); +} + +static DECLCALLBACK(int) handleVDMessage(void *pvUser, const char *pszFormat, va_list va) +{ + NOREF(pvUser); + return RTPrintfV(pszFormat, va); +} + +static RTEXITCODE CmdSetHDUUID(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + Guid uuid; + RTUUID rtuuid; + enum eUuidType { + HDUUID, + HDPARENTUUID + } uuidType; + + if (!strcmp(argv[0], "sethduuid")) + { + uuidType = HDUUID; + if (argc != 3 && argc != 2) + return errorSyntaxInternal(USAGE_I_SETHDUUID, Internal::tr("Not enough parameters")); + /* if specified, take UUID, otherwise generate a new one */ + if (argc == 3) + { + if (RT_FAILURE(RTUuidFromStr(&rtuuid, argv[2]))) + return errorSyntaxInternal(USAGE_I_SETHDUUID, Internal::tr("Invalid UUID parameter")); + uuid = argv[2]; + } else + uuid.create(); + } + else if (!strcmp(argv[0], "sethdparentuuid")) + { + uuidType = HDPARENTUUID; + if (argc != 3) + return errorSyntaxInternal(USAGE_I_SETHDPARENTUUID, Internal::tr("Not enough parameters")); + if (RT_FAILURE(RTUuidFromStr(&rtuuid, argv[2]))) + return errorSyntaxInternal(USAGE_I_SETHDPARENTUUID, Internal::tr("Invalid UUID parameter")); + uuid = argv[2]; + } + else + return errorSyntaxInternal(USAGE_I_SETHDUUID, Internal::tr("Invalid invocation")); + + /* just try it */ + char *pszFormat = NULL; + VDTYPE enmType = VDTYPE_INVALID; + int vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, argv[1], VDTYPE_INVALID, &pszFormat, &enmType); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Format autodetect failed: %Rrc"), vrc); + + PVDISK pDisk = NULL; + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = handleVDMessage; + + vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + vrc = VDCreate(pVDIfs, enmType, &pDisk); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot create the virtual disk container: %Rrc"), vrc); + + /* Open the image */ + vrc = VDOpen(pDisk, pszFormat, argv[1], VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_INFO, NULL); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot open the image: %Rrc"), vrc); + + if (uuidType == HDUUID) + vrc = VDSetUuid(pDisk, VD_LAST_IMAGE, uuid.raw()); + else + vrc = VDSetParentUuid(pDisk, VD_LAST_IMAGE, uuid.raw()); + if (RT_FAILURE(vrc)) + RTMsgError(Internal::tr("Cannot set a new UUID: %Rrc"), vrc); + else + RTPrintf(Internal::tr("UUID changed to: %s\n"), uuid.toString().c_str()); + + VDCloseAll(pDisk); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static RTEXITCODE CmdDumpHDInfo(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + + /* we need exactly one parameter: the image file */ + if (argc != 1) + { + return errorSyntaxInternal(USAGE_I_DUMPHDINFO, Internal::tr("Not enough parameters")); + } + + /* just try it */ + char *pszFormat = NULL; + VDTYPE enmType = VDTYPE_INVALID; + int vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, argv[0], VDTYPE_INVALID, &pszFormat, &enmType); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Format autodetect failed: %Rrc"), vrc); + + PVDISK pDisk = NULL; + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = handleVDMessage; + + vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + vrc = VDCreate(pVDIfs, enmType, &pDisk); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot create the virtual disk container: %Rrc"), vrc); + + /* Open the image */ + vrc = VDOpen(pDisk, pszFormat, argv[0], VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, NULL); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot open the image: %Rrc"), vrc); + + VDDumpImages(pDisk); + + VDCloseAll(pDisk); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static int partRead(RTFILE File, PHOSTPARTITIONS pPart) +{ + uint8_t aBuffer[512]; + uint8_t partitionTableHeader[512]; + uint32_t sector_size = 512; + uint64_t lastUsableLBA = 0; + + VDISKPARTTYPE partitioningType; + + pPart->cPartitions = 0; + memset(pPart->aPartitions, '\0', sizeof(pPart->aPartitions)); + + int vrc = RTFileReadAt(File, 0, &aBuffer, sizeof(aBuffer), NULL); + if (RT_FAILURE(vrc)) + return vrc; + + if (aBuffer[450] == 0xEE)/* check the sign of the GPT disk*/ + { + partitioningType = VDISKPARTTYPE_GPT; + pPart->uPartitioningType = VDISKPARTTYPE_GPT;//partitioningType; + + if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) + return VERR_INVALID_PARAMETER; + + vrc = RTFileReadAt(File, sector_size, &partitionTableHeader, sector_size, NULL); + if (RT_SUCCESS(vrc)) + { + /** @todo r=bird: This is a 64-bit magic value, right... */ + const char *l_ppth = (char *)partitionTableHeader; + if (strncmp(l_ppth, "EFI PART", 8)) + return VERR_INVALID_PARAMETER; + + /** @todo check GPT Version */ + + /** @todo r=bird: C have this handy concept called structures which + * greatly simplify data access... (Someone is really lazy here!) */ +#if 0 /* unused */ + uint64_t firstUsableLBA = RT_MAKE_U64_FROM_U8(partitionTableHeader[40], + partitionTableHeader[41], + partitionTableHeader[42], + partitionTableHeader[43], + partitionTableHeader[44], + partitionTableHeader[45], + partitionTableHeader[46], + partitionTableHeader[47] + ); +#endif + lastUsableLBA = RT_MAKE_U64_FROM_U8(partitionTableHeader[48], + partitionTableHeader[49], + partitionTableHeader[50], + partitionTableHeader[51], + partitionTableHeader[52], + partitionTableHeader[53], + partitionTableHeader[54], + partitionTableHeader[55] + ); + uint32_t partitionsNumber = RT_MAKE_U32_FROM_U8(partitionTableHeader[80], + partitionTableHeader[81], + partitionTableHeader[82], + partitionTableHeader[83] + ); + uint32_t partitionEntrySize = RT_MAKE_U32_FROM_U8(partitionTableHeader[84], + partitionTableHeader[85], + partitionTableHeader[86], + partitionTableHeader[87] + ); + + uint32_t currentEntry = 0; + + if (partitionEntrySize * partitionsNumber > 4 * _1M) + { + RTMsgError(Internal::tr("The GPT header seems corrupt because it contains too many entries")); + return VERR_INVALID_PARAMETER; + } + + uint8_t *pbPartTable = (uint8_t *)RTMemAllocZ(RT_ALIGN_Z(partitionEntrySize * partitionsNumber, 512)); + if (!pbPartTable) + { + RTMsgError(Internal::tr("Allocating memory for the GPT partitions entries failed")); + return VERR_NO_MEMORY; + } + + /* partition entries begin from LBA2 */ + /** @todo r=aeichner: Reading from LBA 2 is not always correct, the header will contain the starting LBA. */ + vrc = RTFileReadAt(File, 1024, pbPartTable, RT_ALIGN_Z(partitionEntrySize * partitionsNumber, 512), NULL); + if (RT_FAILURE(vrc)) + { + RTMsgError(Internal::tr("Reading the partition table failed")); + RTMemFree(pbPartTable); + return vrc; + } + + while (currentEntry < partitionsNumber) + { + uint8_t *partitionEntry = pbPartTable + currentEntry * partitionEntrySize; + + uint64_t start = RT_MAKE_U64_FROM_U8(partitionEntry[32], partitionEntry[33], partitionEntry[34], partitionEntry[35], + partitionEntry[36], partitionEntry[37], partitionEntry[38], partitionEntry[39]); + uint64_t end = RT_MAKE_U64_FROM_U8(partitionEntry[40], partitionEntry[41], partitionEntry[42], partitionEntry[43], + partitionEntry[44], partitionEntry[45], partitionEntry[46], partitionEntry[47]); + + PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; + pCP->uIndex = currentEntry + 1; + pCP->uIndexWin = currentEntry + 1; + pCP->uType = 0; + pCP->uStartCylinder = 0; + pCP->uStartHead = 0; + pCP->uStartSector = 0; + pCP->uEndCylinder = 0; + pCP->uEndHead = 0; + pCP->uEndSector = 0; + pCP->uPartDataStart = 0; /* will be filled out later properly. */ + pCP->cPartDataSectors = 0; + if (start==0 || end==0) + { + pCP->uIndex = 0; + pCP->uIndexWin = 0; + --pPart->cPartitions; + break; + } + else + { + pCP->uStart = start; + pCP->uSize = (end +1) - start;/*+1 LBA because the last address is included*/ + } + + ++currentEntry; + } + + RTMemFree(pbPartTable); + } + } + else + { + partitioningType = VDISKPARTTYPE_MBR; + pPart->uPartitioningType = VDISKPARTTYPE_MBR;//partitioningType; + + if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) + return VERR_INVALID_PARAMETER; + + unsigned uExtended = (unsigned)-1; + unsigned uIndexWin = 1; + + for (unsigned i = 0; i < 4; i++) + { + uint8_t *p = &aBuffer[0x1be + i * 16]; + if (p[4] == 0) + continue; + PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; + pCP->uIndex = i + 1; + pCP->uType = p[4]; + pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); + pCP->uStartHead = p[1]; + pCP->uStartSector = p[2] & 0x3f; + pCP->uEndCylinder = (uint32_t)p[7] + ((uint32_t)(p[6] & 0xc0) << 2); + pCP->uEndHead = p[5]; + pCP->uEndSector = p[6] & 0x3f; + pCP->uStart = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); + pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); + pCP->uPartDataStart = 0; /* will be filled out later properly. */ + pCP->cPartDataSectors = 0; + + if (PARTTYPE_IS_EXTENDED(p[4])) + { + if (uExtended == (unsigned)-1) + { + uExtended = (unsigned)(pCP - pPart->aPartitions); + pCP->uIndexWin = 0; + } + else + { + RTMsgError(Internal::tr("More than one extended partition")); + return VERR_INVALID_PARAMETER; + } + } + else + { + pCP->uIndexWin = uIndexWin; + uIndexWin++; + } + } + + if (uExtended != (unsigned)-1) + { + unsigned uIndex = 5; + uint64_t uStart = pPart->aPartitions[uExtended].uStart; + uint64_t uOffset = 0; + if (!uStart) + { + RTMsgError(Internal::tr("Inconsistency for logical partition start")); + return VERR_INVALID_PARAMETER; + } + + do + { + vrc = RTFileReadAt(File, (uStart + uOffset) * 512, &aBuffer, sizeof(aBuffer), NULL); + if (RT_FAILURE(vrc)) + return vrc; + + if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) + { + RTMsgError(Internal::tr("Logical partition without magic")); + return VERR_INVALID_PARAMETER; + } + uint8_t *p = &aBuffer[0x1be]; + + if (p[4] == 0) + { + RTMsgError(Internal::tr("Logical partition with type 0 encountered")); + return VERR_INVALID_PARAMETER; + } + + PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; + pCP->uIndex = uIndex; + pCP->uIndexWin = uIndexWin; + pCP->uType = p[4]; + pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); + pCP->uStartHead = p[1]; + pCP->uStartSector = p[2] & 0x3f; + pCP->uEndCylinder = (uint32_t)p[7] + ((uint32_t)(p[6] & 0xc0) << 2); + pCP->uEndHead = p[5]; + pCP->uEndSector = p[6] & 0x3f; + uint32_t uStartOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); + if (!uStartOffset) + { + RTMsgError(Internal::tr("Invalid partition start offset")); + return VERR_INVALID_PARAMETER; + } + pCP->uStart = uStart + uOffset + uStartOffset; + pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); + /* Fill out partitioning location info for EBR. */ + pCP->uPartDataStart = uStart + uOffset; + pCP->cPartDataSectors = uStartOffset; + p += 16; + if (p[4] == 0) + uExtended = (unsigned)-1; + else if (PARTTYPE_IS_EXTENDED(p[4])) + { + uExtended = uIndex; + uIndex++; + uIndexWin++; + uOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); + } + else + { + RTMsgError(Internal::tr("Logical partition chain broken")); + return VERR_INVALID_PARAMETER; + } + } while (uExtended != (unsigned)-1); + } + } + + + /* Sort partitions in ascending order of start sector, plus a trivial + * bit of consistency checking. */ + for (unsigned i = 0; i < pPart->cPartitions-1; i++) + { + unsigned uMinIdx = i; + uint64_t uMinVal = pPart->aPartitions[i].uStart; + for (unsigned j = i + 1; j < pPart->cPartitions; j++) + { + if (pPart->aPartitions[j].uStart < uMinVal) + { + uMinIdx = j; + uMinVal = pPart->aPartitions[j].uStart; + } + else if (pPart->aPartitions[j].uStart == uMinVal) + { + RTMsgError(Internal::tr("Two partitions start at the same place")); + return VERR_INVALID_PARAMETER; + } + else if (pPart->aPartitions[j].uStart == 0) + { + RTMsgError(Internal::tr("Partition starts at sector 0")); + return VERR_INVALID_PARAMETER; + } + } + if (uMinIdx != i) + { + /* Swap entries at index i and uMinIdx. */ + memcpy(&pPart->aPartitions[pPart->cPartitions], + &pPart->aPartitions[i], sizeof(HOSTPARTITION)); + memcpy(&pPart->aPartitions[i], + &pPart->aPartitions[uMinIdx], sizeof(HOSTPARTITION)); + memcpy(&pPart->aPartitions[uMinIdx], + &pPart->aPartitions[pPart->cPartitions], sizeof(HOSTPARTITION)); + } + } + + /* Fill out partitioning location info for MBR or GPT. */ + pPart->aPartitions[0].uPartDataStart = 0; + pPart->aPartitions[0].cPartDataSectors = pPart->aPartitions[0].uStart; + + /* Fill out partitioning location info for backup GPT. */ + if (partitioningType == VDISKPARTTYPE_GPT) + { + pPart->aPartitions[pPart->cPartitions-1].uPartDataStart = lastUsableLBA+1; + pPart->aPartitions[pPart->cPartitions-1].cPartDataSectors = 33; + + /* Now do a some partition table consistency checking, to reject the most + * obvious garbage which can lead to trouble later. */ + uint64_t uPrevEnd = 0; + for (unsigned i = 0; i < pPart->cPartitions; i++) + { + if (pPart->aPartitions[i].cPartDataSectors) + uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; + if (pPart->aPartitions[i].uStart < uPrevEnd && + pPart->cPartitions-1 != i) + { + RTMsgError(Internal::tr("Overlapping GPT partitions")); + return VERR_INVALID_PARAMETER; + } + } + } + else + { + /* Now do a some partition table consistency checking, to reject the most + * obvious garbage which can lead to trouble later. */ + uint64_t uPrevEnd = 0; + for (unsigned i = 0; i < pPart->cPartitions; i++) + { + if (pPart->aPartitions[i].cPartDataSectors) + uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; + if (pPart->aPartitions[i].uStart < uPrevEnd) + { + RTMsgError(Internal::tr("Overlapping MBR partitions")); + return VERR_INVALID_PARAMETER; + } + if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType)) + uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize; + } + } + + return VINF_SUCCESS; +} + +static RTEXITCODE CmdListPartitions(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + Utf8Str rawdisk; + + /* let's have a closer look at the arguments */ + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "-rawdisk") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + rawdisk = argv[i]; + } + else + { + return errorSyntaxInternal(USAGE_I_LISTPARTITIONS, Internal::tr("Invalid parameter '%s'"), argv[i]); + } + } + + if (rawdisk.isEmpty()) + return errorSyntaxInternal(USAGE_I_LISTPARTITIONS, Internal::tr("Mandatory parameter -rawdisk missing")); + + RTFILE hRawFile; + int vrc = RTFileOpen(&hRawFile, rawdisk.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot open the raw disk: %Rrc"), vrc); + + HOSTPARTITIONS partitions; + vrc = partRead(hRawFile, &partitions); + /* Don't bail out on errors, print the table and return the result code. */ + + RTPrintf(Internal::tr("Number Type StartCHS EndCHS Size (MiB) Start (Sect)\n")); + for (unsigned i = 0; i < partitions.cPartitions; i++) + { + /* Don't show the extended partition, otherwise users might think they + * can add it to the list of partitions for raw partition access. */ + if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) + continue; + + RTPrintf("%-7u %#04x %-4u/%-3u/%-2u %-4u/%-3u/%-2u %10llu %10llu\n", + partitions.aPartitions[i].uIndex, + partitions.aPartitions[i].uType, + partitions.aPartitions[i].uStartCylinder, + partitions.aPartitions[i].uStartHead, + partitions.aPartitions[i].uStartSector, + partitions.aPartitions[i].uEndCylinder, + partitions.aPartitions[i].uEndHead, + partitions.aPartitions[i].uEndSector, + partitions.aPartitions[i].uSize / 2048, + partitions.aPartitions[i].uStart); + } + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aCreateRawVMDKOptions[] = +{ + { "--filename", 'f', RTGETOPT_REQ_STRING }, + { "-filename", 'f', RTGETOPT_REQ_STRING }, + { "--rawdisk", 'd', RTGETOPT_REQ_STRING }, + { "-rawdisk", 'd', RTGETOPT_REQ_STRING }, + { "--partitions", 'p', RTGETOPT_REQ_STRING }, + { "-partitions", 'p', RTGETOPT_REQ_STRING }, + { "--mbr", 'm', RTGETOPT_REQ_STRING }, + { "-mbr", 'm', RTGETOPT_REQ_STRING }, +#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_WINDOWS) + { "--relative", 'r', RTGETOPT_REQ_NOTHING }, + { "-relative", 'r', RTGETOPT_REQ_NOTHING }, +#endif /* RT_OS_LINUX || RT_OS_FREEBSD || RT_OS_WINDOWS */ +}; + +static RTEXITCODE CmdCreateRawVMDK(int argc, char **argv, HandlerArg *a) +{ + const char *pszFilename = NULL; + const char *pszRawdisk = NULL; + const char *pszPartitions = NULL; + const char *pszMbr = NULL; + bool fRelative = false; + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, g_aCreateRawVMDKOptions, RT_ELEMENTS(g_aCreateRawVMDKOptions), 0, 0); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'f': // --filename + pszFilename = ValueUnion.psz; + break; + + case 'd': // --rawdisk + pszRawdisk = ValueUnion.psz; + break; + + case 'p': // --partitions + pszPartitions = ValueUnion.psz; + break; + + case 'm': // --mbr + pszMbr = ValueUnion.psz; + break; +#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_WINDOWS) + case 'r': // --relative + fRelative = true; + break; +#endif /* RT_OS_LINUX || RT_OS_FREEBSD || RT_OS_WINDOWS */ + + default: + return errorGetOptInternal(USAGE_I_CREATERAWVMDK, c, &ValueUnion); + } + } + + if (!pszFilename || !*pszFilename) + return errorSyntaxInternal(USAGE_I_CREATERAWVMDK, Internal::tr("Mandatory parameter --filename missing")); + if (!pszRawdisk || !*pszRawdisk) + return errorSyntaxInternal(USAGE_I_CREATERAWVMDK, Internal::tr("Mandatory parameter --rawdisk missing")); + if (!pszPartitions && pszMbr) + return errorSyntaxInternal(USAGE_I_CREATERAWVMDK, + Internal::tr("The parameter --mbr is only valid when the parameter -partitions is also present")); + + /* Construct the equivalent 'VBoxManage createmedium disk --variant RawDisk ...' command line. */ + size_t cMaxArgs = 9; /* all possible 'createmedium' args based on the 'createrawvmdk' options + 1 for NULL */ + char **papszNewArgv = (char **)RTMemAllocZ(sizeof(papszNewArgv[0]) * cMaxArgs); + if (!papszNewArgv) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Failed to allocate memory for argument array")); + int cArgs = 0; + + papszNewArgv[cArgs++] = RTStrDup("disk"); + papszNewArgv[cArgs++] = RTStrDup("--variant=RawDisk"); + papszNewArgv[cArgs++] = RTStrDup("--format=VMDK"); + + for (int i = 0; i < cArgs; i++) + if (!papszNewArgv[i]) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Failed to allocate memory for argument array")); + + if ( RTStrAPrintf(&papszNewArgv[cArgs++], "--filename=%s", pszFilename) == -1 + || RTStrAPrintf(&papszNewArgv[cArgs++], "--property=RawDrive=%s", pszRawdisk) == -1 + || (pszPartitions && (RTStrAPrintf(&papszNewArgv[cArgs++], "--property=Partitions=%s", pszPartitions) == -1)) + || (pszMbr && (RTStrAPrintf(&papszNewArgv[cArgs++], "--property-filename=%s", pszMbr) == -1)) + || (fRelative && (RTStrAPrintf(&papszNewArgv[cArgs++], "--property=Relative=%d", fRelative) == -1))) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Failed to allocate memory for argument array")); + + papszNewArgv[cArgs] = NULL; + + RTStrmPrintf(g_pStdErr, + Internal::tr("\nThe 'createrawvdk' subcommand is deprecated. The equivalent functionality is\n" + "available using the 'VBoxManage createmedium' command and should be used\n" + "instead. See 'VBoxManage help createmedium' for details.\n\n")); + + a->argc = cArgs; + a->argv = papszNewArgv; + RTEXITCODE rcExit = handleCreateMedium(a); + + for (int i = 0; i < cArgs; i++) + RTStrFree(papszNewArgv[i]); + RTMemFree(papszNewArgv); + + return rcExit; +} + +static RTEXITCODE CmdRenameVMDK(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + Utf8Str src; + Utf8Str dst; + /* Parse the arguments. */ + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "-from") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + src = argv[i]; + } + else if (strcmp(argv[i], "-to") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + dst = argv[i]; + } + else + { + return errorSyntaxInternal(USAGE_I_RENAMEVMDK, Internal::tr("Invalid parameter '%s'"), argv[i]); + } + } + + if (src.isEmpty()) + return errorSyntaxInternal(USAGE_I_RENAMEVMDK, Internal::tr("Mandatory parameter -from missing")); + if (dst.isEmpty()) + return errorSyntaxInternal(USAGE_I_RENAMEVMDK, Internal::tr("Mandatory parameter -to missing")); + + PVDISK pDisk = NULL; + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = handleVDMessage; + + int vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + vrc = VDCreate(pVDIfs, VDTYPE_HDD, &pDisk); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot create the virtual disk container: %Rrc"), vrc); + + vrc = VDOpen(pDisk, "VMDK", src.c_str(), VD_OPEN_FLAGS_NORMAL, NULL); + if (RT_SUCCESS(vrc)) + { + vrc = VDCopy(pDisk, 0, pDisk, "VMDK", dst.c_str(), true, 0, + VD_IMAGE_FLAGS_NONE, NULL, VD_OPEN_FLAGS_NORMAL, + NULL, NULL, NULL); + if (RT_FAILURE(vrc)) + RTMsgError(Internal::tr("Cannot rename the image: %Rrc"), vrc); + } + else + RTMsgError(Internal::tr("Cannot create the source image: %Rrc"), vrc); + VDCloseAll(pDisk); + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE CmdConvertToRaw(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + Utf8Str srcformat; + Utf8Str src; + Utf8Str dst; + bool fWriteToStdOut = false; + + /* Parse the arguments. */ + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "-format") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + srcformat = argv[i]; + } + else if (src.isEmpty()) + { + src = argv[i]; + } + else if (dst.isEmpty()) + { + dst = argv[i]; +#ifdef ENABLE_CONVERT_RAW_TO_STDOUT + if (!strcmp(argv[i], "stdout")) + fWriteToStdOut = true; +#endif /* ENABLE_CONVERT_RAW_TO_STDOUT */ + } + else + { + return errorSyntaxInternal(USAGE_I_CONVERTTORAW, Internal::tr("Invalid parameter '%s'"), argv[i]); + } + } + + if (src.isEmpty()) + return errorSyntaxInternal(USAGE_I_CONVERTTORAW, Internal::tr("Mandatory filename parameter missing")); + if (dst.isEmpty()) + return errorSyntaxInternal(USAGE_I_CONVERTTORAW, Internal::tr("Mandatory outputfile parameter missing")); + + PVDISK pDisk = NULL; + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = handleVDMessage; + + int vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + /** @todo Support convert to raw for floppy and DVD images too. */ + vrc = VDCreate(pVDIfs, VDTYPE_HDD, &pDisk); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot create the virtual disk container: %Rrc"), vrc); + + /* Open raw output file. */ + RTFILE outFile; + vrc = VINF_SUCCESS; + if (fWriteToStdOut) + vrc = RTFileFromNative(&outFile, 1); + else + vrc = RTFileOpen(&outFile, dst.c_str(), RTFILE_O_WRITE | RTFILE_O_CREATE | RTFILE_O_DENY_ALL); + if (RT_FAILURE(vrc)) + { + VDCloseAll(pDisk); + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot create destination file \"%s\": %Rrc"), + dst.c_str(), vrc); + } + + if (srcformat.isEmpty()) + { + char *pszFormat = NULL; + VDTYPE enmType = VDTYPE_INVALID; + vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, + src.c_str(), VDTYPE_INVALID, &pszFormat, &enmType); + if (RT_FAILURE(vrc) || enmType != VDTYPE_HDD) + { + VDCloseAll(pDisk); + if (!fWriteToStdOut) + { + RTFileClose(outFile); + RTFileDelete(dst.c_str()); + } + if (RT_FAILURE(vrc)) + RTMsgError(Internal::tr("No file format specified and autodetect failed - please specify format: %Rrc"), + vrc); + else + RTMsgError(Internal::tr("Only converting harddisk images is supported")); + return RTEXITCODE_FAILURE; + } + srcformat = pszFormat; + RTStrFree(pszFormat); + } + vrc = VDOpen(pDisk, srcformat.c_str(), src.c_str(), VD_OPEN_FLAGS_READONLY, NULL); + if (RT_FAILURE(vrc)) + { + VDCloseAll(pDisk); + if (!fWriteToStdOut) + { + RTFileClose(outFile); + RTFileDelete(dst.c_str()); + } + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot open the source image: %Rrc"), vrc); + } + + uint64_t cbSize = VDGetSize(pDisk, VD_LAST_IMAGE); + uint64_t offFile = 0; +#define RAW_BUFFER_SIZE _128K + size_t cbBuf = RAW_BUFFER_SIZE; + void *pvBuf = RTMemAlloc(cbBuf); + if (pvBuf) + { + RTStrmPrintf(g_pStdErr, Internal::tr("Converting image \"%s\" with size %RU64 bytes (%RU64MB) to raw...\n", "", cbSize), + src.c_str(), cbSize, (cbSize + _1M - 1) / _1M); + while (offFile < cbSize) + { + size_t cb = (size_t)RT_MIN(cbSize - offFile, cbBuf); + vrc = VDRead(pDisk, offFile, pvBuf, cb); + if (RT_FAILURE(vrc)) + break; + vrc = RTFileWrite(outFile, pvBuf, cb, NULL); + if (RT_FAILURE(vrc)) + break; + offFile += cb; + } + RTMemFree(pvBuf); + if (RT_FAILURE(vrc)) + { + VDCloseAll(pDisk); + if (!fWriteToStdOut) + { + RTFileClose(outFile); + RTFileDelete(dst.c_str()); + } + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Cannot copy image data: %Rrc"), vrc); + } + } + else + { + vrc = VERR_NO_MEMORY; + VDCloseAll(pDisk); + if (!fWriteToStdOut) + { + RTFileClose(outFile); + RTFileDelete(dst.c_str()); + } + return RTMsgErrorExit(RTEXITCODE_FAILURE, Internal::tr("Out of memory allocating read buffer")); + } + + if (!fWriteToStdOut) + RTFileClose(outFile); + VDCloseAll(pDisk); + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE CmdConvertHardDisk(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + Utf8Str srcformat; + Utf8Str dstformat; + Utf8Str src; + Utf8Str dst; + int vrc; + PVDISK pSrcDisk = NULL; + PVDISK pDstDisk = NULL; + VDTYPE enmSrcType = VDTYPE_INVALID; + + /* Parse the arguments. */ + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "-srcformat") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + srcformat = argv[i]; + } + else if (strcmp(argv[i], "-dstformat") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + dstformat = argv[i]; + } + else if (src.isEmpty()) + { + src = argv[i]; + } + else if (dst.isEmpty()) + { + dst = argv[i]; + } + else + { + return errorSyntaxInternal(USAGE_I_CONVERTHD, Internal::tr("Invalid parameter '%s'"), argv[i]); + } + } + + if (src.isEmpty()) + return errorSyntaxInternal(USAGE_I_CONVERTHD, Internal::tr("Mandatory input image parameter missing")); + if (dst.isEmpty()) + return errorSyntaxInternal(USAGE_I_CONVERTHD, Internal::tr("Mandatory output image parameter missing")); + + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = handleVDMessage; + + vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + do + { + /* Try to determine input image format */ + if (srcformat.isEmpty()) + { + char *pszFormat = NULL; + vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, + src.c_str(), VDTYPE_HDD, &pszFormat, &enmSrcType); + if (RT_FAILURE(vrc)) + { + RTMsgError(Internal::tr("No file format specified and autodetect failed - please specify format: %Rrc"), + vrc); + break; + } + srcformat = pszFormat; + RTStrFree(pszFormat); + } + + vrc = VDCreate(pVDIfs, enmSrcType, &pSrcDisk); + if (RT_FAILURE(vrc)) + { + RTMsgError(Internal::tr("Cannot create the source virtual disk container: %Rrc"), vrc); + break; + } + + /* Open the input image */ + vrc = VDOpen(pSrcDisk, srcformat.c_str(), src.c_str(), VD_OPEN_FLAGS_READONLY, NULL); + if (RT_FAILURE(vrc)) + { + RTMsgError(Internal::tr("Cannot open the source image: %Rrc"), vrc); + break; + } + + /* Output format defaults to VDI */ + if (dstformat.isEmpty()) + dstformat = "VDI"; + + vrc = VDCreate(pVDIfs, enmSrcType, &pDstDisk); + if (RT_FAILURE(vrc)) + { + RTMsgError(Internal::tr("Cannot create the destination virtual disk container: %Rrc"), vrc); + break; + } + + uint64_t cbSize = VDGetSize(pSrcDisk, VD_LAST_IMAGE); + RTStrmPrintf(g_pStdErr, Internal::tr("Converting image \"%s\" with size %RU64 bytes (%RU64MB)...\n", "", cbSize), + src.c_str(), cbSize, (cbSize + _1M - 1) / _1M); + + /* Create the output image */ + vrc = VDCopy(pSrcDisk, VD_LAST_IMAGE, pDstDisk, dstformat.c_str(), + dst.c_str(), false, 0, VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED, + NULL, VD_OPEN_FLAGS_NORMAL, NULL, NULL, NULL); + if (RT_FAILURE(vrc)) + { + RTMsgError(Internal::tr("Cannot copy the image: %Rrc"), vrc); + break; + } + } + while (0); + if (pDstDisk) + VDCloseAll(pDstDisk); + if (pSrcDisk) + VDCloseAll(pSrcDisk); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * Tries to repair a corrupted hard disk image. + * + * @returns VBox status code + */ +static RTEXITCODE CmdRepairHardDisk(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + Utf8Str image; + Utf8Str format; + int vrc; + bool fDryRun = false; + + /* Parse the arguments. */ + for (int i = 0; i < argc; i++) + { + if (strcmp(argv[i], "-dry-run") == 0) + { + fDryRun = true; + } + else if (strcmp(argv[i], "-format") == 0) + { + if (argc <= i + 1) + { + return errorArgument(Internal::tr("Missing argument to '%s'"), argv[i]); + } + i++; + format = argv[i]; + } + else if (image.isEmpty()) + { + image = argv[i]; + } + else + { + return errorSyntaxInternal(USAGE_I_REPAIRHD, Internal::tr("Invalid parameter '%s'"), argv[i]); + } + } + + if (image.isEmpty()) + return errorSyntaxInternal(USAGE_I_REPAIRHD, Internal::tr("Mandatory input image parameter missing")); + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = handleVDMessage; + + vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + do + { + /* Try to determine input image format */ + if (format.isEmpty()) + { + char *pszFormat = NULL; + VDTYPE enmSrcType = VDTYPE_INVALID; + + vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */, + image.c_str(), VDTYPE_HDD, &pszFormat, &enmSrcType); + if (RT_FAILURE(vrc) && (vrc != VERR_VD_IMAGE_CORRUPTED)) + { + RTMsgError(Internal::tr("No file format specified and autodetect failed - please specify format: %Rrc"), + vrc); + break; + } + format = pszFormat; + RTStrFree(pszFormat); + } + + uint32_t fFlags = 0; + if (fDryRun) + fFlags |= VD_REPAIR_DRY_RUN; + + vrc = VDRepair(pVDIfs, NULL, image.c_str(), format.c_str(), fFlags); + } + while (0); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * Unloads the necessary driver. + * + * @returns VBox status code + */ +static RTEXITCODE CmdModUninstall(void) +{ + int vrc = SUPR3Uninstall(); + if (RT_SUCCESS(vrc) || vrc == VERR_NOT_IMPLEMENTED) + return RTEXITCODE_SUCCESS; + return RTEXITCODE_FAILURE; +} + +/** + * Loads the necessary driver. + * + * @returns VBox status code + */ +static RTEXITCODE CmdModInstall(void) +{ + int vrc = SUPR3Install(); + if (RT_SUCCESS(vrc) || vrc == VERR_NOT_IMPLEMENTED) + return RTEXITCODE_SUCCESS; + return RTEXITCODE_FAILURE; +} + +static RTEXITCODE CmdDebugLog(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + /* + * The first parameter is the name or UUID of a VM with a direct session + * that we wish to open. + */ + if (argc < 1) + return errorSyntaxInternal(USAGE_I_DEBUGLOG, Internal::tr("Missing VM name/UUID")); + + ComPtr<IMachine> ptrMachine; + HRESULT hrc; + CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]).raw(), + ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + + CHECK_ERROR_RET(ptrMachine, LockMachine(aSession, LockType_Shared), RTEXITCODE_FAILURE); + + /* + * Get the debugger interface. + */ + ComPtr<IConsole> ptrConsole; + CHECK_ERROR_RET(aSession, COMGETTER(Console)(ptrConsole.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IMachineDebugger> ptrDebugger; + CHECK_ERROR_RET(ptrConsole, COMGETTER(Debugger)(ptrDebugger.asOutParam()), RTEXITCODE_FAILURE); + + /* + * Parse the command. + */ + bool fEnablePresent = false; + bool fEnable = false; + bool fFlagsPresent = false; + RTCString strFlags; + bool fGroupsPresent = false; + RTCString strGroups; + bool fDestsPresent = false; + RTCString strDests; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--disable", 'E', RTGETOPT_REQ_NOTHING }, + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "--flags", 'f', RTGETOPT_REQ_STRING }, + { "--groups", 'g', RTGETOPT_REQ_STRING }, + { "--destinations", 'd', RTGETOPT_REQ_STRING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'e': + fEnablePresent = true; + fEnable = true; + break; + + case 'E': + fEnablePresent = true; + fEnable = false; + break; + + case 'f': + fFlagsPresent = true; + if (*ValueUnion.psz) + { + if (strFlags.isNotEmpty()) + strFlags.append(' '); + strFlags.append(ValueUnion.psz); + } + break; + + case 'g': + fGroupsPresent = true; + if (*ValueUnion.psz) + { + if (strGroups.isNotEmpty()) + strGroups.append(' '); + strGroups.append(ValueUnion.psz); + } + break; + + case 'd': + fDestsPresent = true; + if (*ValueUnion.psz) + { + if (strDests.isNotEmpty()) + strDests.append(' '); + strDests.append(ValueUnion.psz); + } + break; + + default: + return errorGetOptInternal(USAGE_I_DEBUGLOG, ch, &ValueUnion); + } + } + + /* + * Do the job. + */ + if (fEnablePresent && !fEnable) + CHECK_ERROR_RET(ptrDebugger, COMSETTER(LogEnabled)(FALSE), RTEXITCODE_FAILURE); + + /** @todo flags, groups destination. */ + if (fFlagsPresent || fGroupsPresent || fDestsPresent) + RTMsgWarning(Internal::tr("One or more of the requested features are not implemented! Feel free to do this.")); + + if (fEnablePresent && fEnable) + CHECK_ERROR_RET(ptrDebugger, COMSETTER(LogEnabled)(TRUE), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + +/** + * Generate a SHA-256 password hash + */ +static RTEXITCODE CmdGeneratePasswordHash(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + RT_NOREF(aVirtualBox, aSession); + + /* one parameter, the password to hash */ + if (argc != 1) + return errorSyntaxInternal(USAGE_I_PASSWORDHASH, Internal::tr("password to hash required")); + + uint8_t abDigest[RTSHA256_HASH_SIZE]; + RTSha256(argv[0], strlen(argv[0]), abDigest); + char pszDigest[RTSHA256_DIGEST_LEN + 1]; + RTSha256ToString(abDigest, pszDigest, sizeof(pszDigest)); + RTPrintf(Internal::tr("Password hash: %s\n"), pszDigest); + + return RTEXITCODE_SUCCESS; +} + +/** + * Print internal guest statistics or + * set internal guest statistics update interval if specified + */ +static RTEXITCODE CmdGuestStats(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) +{ + /* one parameter, guest name */ + if (argc < 1) + return errorSyntaxInternal(USAGE_I_GUESTSTATS, Internal::tr("Missing VM name/UUID")); + + /* + * Parse the command. + */ + ULONG aUpdateInterval = 0; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--interval", 'i', RTGETOPT_REQ_UINT32 } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'i': + aUpdateInterval = ValueUnion.u32; + break; + + default: + return errorGetOptInternal(USAGE_I_GUESTSTATS, ch, &ValueUnion); + } + } + + if (argc > 1 && aUpdateInterval == 0) + return errorSyntaxInternal(USAGE_I_GUESTSTATS, Internal::tr("Invalid update interval specified")); + + RTPrintf(Internal::tr("argc=%d interval=%u\n"), argc, aUpdateInterval); + + ComPtr<IMachine> ptrMachine; + HRESULT hrc; + CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]).raw(), + ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + + CHECK_ERROR_RET(ptrMachine, LockMachine(aSession, LockType_Shared), RTEXITCODE_FAILURE); + + /* + * Get the guest interface. + */ + ComPtr<IConsole> ptrConsole; + CHECK_ERROR_RET(aSession, COMGETTER(Console)(ptrConsole.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IGuest> ptrGuest; + CHECK_ERROR_RET(ptrConsole, COMGETTER(Guest)(ptrGuest.asOutParam()), RTEXITCODE_FAILURE); + + if (aUpdateInterval) + CHECK_ERROR_RET(ptrGuest, COMSETTER(StatisticsUpdateInterval)(aUpdateInterval), RTEXITCODE_FAILURE); + else + { + ULONG mCpuUser, mCpuKernel, mCpuIdle; + ULONG mMemTotal, mMemFree, mMemBalloon, mMemShared, mMemCache, mPageTotal; + ULONG ulMemAllocTotal, ulMemFreeTotal, ulMemBalloonTotal, ulMemSharedTotal; + + CHECK_ERROR_RET(ptrGuest, InternalGetStatistics(&mCpuUser, &mCpuKernel, &mCpuIdle, + &mMemTotal, &mMemFree, &mMemBalloon, &mMemShared, &mMemCache, + &mPageTotal, &ulMemAllocTotal, &ulMemFreeTotal, + &ulMemBalloonTotal, &ulMemSharedTotal), + RTEXITCODE_FAILURE); + RTPrintf("mCpuUser=%u mCpuKernel=%u mCpuIdle=%u\n" + "mMemTotal=%u mMemFree=%u mMemBalloon=%u mMemShared=%u mMemCache=%u\n" + "mPageTotal=%u ulMemAllocTotal=%u ulMemFreeTotal=%u ulMemBalloonTotal=%u ulMemSharedTotal=%u\n", + mCpuUser, mCpuKernel, mCpuIdle, + mMemTotal, mMemFree, mMemBalloon, mMemShared, mMemCache, + mPageTotal, ulMemAllocTotal, ulMemFreeTotal, ulMemBalloonTotal, ulMemSharedTotal); + + } + + return RTEXITCODE_SUCCESS; +} + + +/** + * Wrapper for handling internal commands + */ +RTEXITCODE handleInternalCommands(HandlerArg *a) +{ + /* at least a command is required */ + if (a->argc < 1) + return errorSyntaxInternal(USAGE_I_ALL, Internal::tr("Command missing")); + + /* + * The 'string switch' on command name. + */ + const char *pszCmd = a->argv[0]; + if (!strcmp(pszCmd, "loadmap")) + return CmdLoadMap(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "loadsyms")) + return CmdLoadSyms(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + //if (!strcmp(pszCmd, "unloadsyms")) + // return CmdUnloadSyms(argc - 1, &a->argv[1]); + if (!strcmp(pszCmd, "sethduuid") || !strcmp(pszCmd, "sethdparentuuid")) + return CmdSetHDUUID(a->argc, &a->argv[0], a->virtualBox, a->session); + if (!strcmp(pszCmd, "dumphdinfo")) + return CmdDumpHDInfo(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "listpartitions")) + return CmdListPartitions(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "createrawvmdk")) + return CmdCreateRawVMDK(a->argc - 1, &a->argv[1], a); + if (!strcmp(pszCmd, "renamevmdk")) + return CmdRenameVMDK(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "converttoraw")) + return CmdConvertToRaw(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "converthd")) + return CmdConvertHardDisk(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "modinstall")) + return CmdModInstall(); + if (!strcmp(pszCmd, "moduninstall")) + return CmdModUninstall(); + if (!strcmp(pszCmd, "debuglog")) + return CmdDebugLog(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "passwordhash")) + return CmdGeneratePasswordHash(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "gueststats")) + return CmdGuestStats(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + if (!strcmp(pszCmd, "repairhd")) + return CmdRepairHardDisk(a->argc - 1, &a->argv[1], a->virtualBox, a->session); + + /* default: */ + return errorSyntaxInternal(USAGE_I_ALL, Internal::tr("Invalid command '%s'"), a->argv[0]); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManage.cpp b/src/VBox/Frontends/VBoxManage/VBoxManage.cpp new file mode 100644 index 00000000..1a59c868 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManage.cpp @@ -0,0 +1,950 @@ +/* $Id: VBoxManage.cpp $ */ +/** @file + * VBoxManage - VirtualBox's command-line interface. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/NativeEventQueue.h> + +#include <VBox/com/VirtualBox.h> + +#ifdef VBOX_WITH_VBOXMANAGE_NLS +# include <VBox/com/AutoLock.h> +# include <VBox/com/listeners.h> +#endif + +#include <VBox/version.h> + +#include <iprt/asm.h> +#include <iprt/buildconfig.h> +#include <iprt/ctype.h> +#include <iprt/file.h> +#include <iprt/getopt.h> +#include <iprt/initterm.h> +#include <iprt/log.h> +#include <iprt/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> + +#include <signal.h> + +#include "VBoxManage.h" + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ + +/** The command doesn't need the COM stuff. */ +#define VBMG_CMD_F_NO_COM RT_BIT_32(0) + +#define VBMG_CMD_INTERNAL HELP_CMD_VBOXMANAGE_INVALID + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ + +/** + * VBoxManage command descriptor. + */ +typedef struct VBMGCMD +{ + /** The command. */ + const char *pszCommand; + /** The new help command. */ + enum HELP_CMD_VBOXMANAGE enmCmdHelp; + /** The handler. */ + RTEXITCODE (*pfnHandler)(HandlerArg *pArg); + /** VBMG_CMD_F_XXX, */ + uint32_t fFlags; +} VBMGCMD; +/** Pointer to a const VBoxManage command descriptor. */ +typedef VBMGCMD const *PCVBMGCMD; + + +DECLARE_TRANSLATION_CONTEXT(VBoxManage); + +void setBuiltInHelpLanguage(const char *pszLang); + +#ifdef VBOX_WITH_VBOXMANAGE_NLS +/* listener class for language updates */ +class VBoxEventListener +{ +public: + VBoxEventListener() + {} + + + HRESULT init(void *) + { + return S_OK; + } + + HRESULT init() + { + return S_OK; + } + + void uninit() + { + } + + virtual ~VBoxEventListener() + { + } + + STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent) + { + switch(aType) + { + case VBoxEventType_OnLanguageChanged: + { + /* + * Proceed with uttmost care as we might be racing com::Shutdown() + * and have the ground open up beneath us. + */ + LogFunc(("VBoxEventType_OnLanguageChanged\n")); + VirtualBoxTranslator *pTranslator = VirtualBoxTranslator::tryInstance(); + if (pTranslator) + { + ComPtr<ILanguageChangedEvent> pEvent = aEvent; + Assert(pEvent); + + /* This call may fail if we're racing COM shutdown. */ + com::Bstr bstrLanguageId; + HRESULT hrc = pEvent->COMGETTER(LanguageId)(bstrLanguageId.asOutParam()); + if (SUCCEEDED(hrc)) + { + try + { + com::Utf8Str strLanguageId(bstrLanguageId); + LogFunc(("New language ID: %s\n", strLanguageId.c_str())); + pTranslator->i_loadLanguage(strLanguageId.c_str()); + setBuiltInHelpLanguage(strLanguageId.c_str()); + } + catch (std::bad_alloc &) + { + LogFunc(("Caught bad_alloc")); + } + } + else + LogFunc(("Failed to get new language ID: %Rhrc\n", hrc)); + + pTranslator->release(); + } + break; + } + + default: + AssertFailed(); + } + + return S_OK; + } +}; + +typedef ListenerImpl<VBoxEventListener> VBoxEventListenerImpl; + +VBOX_LISTENER_DECLARE(VBoxEventListenerImpl) +#endif /* !VBOX_WITH_VBOXMANAGE_NLS */ + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/*extern*/ bool g_fDetailedProgress = false; +/** Set by the signal handler. */ +static volatile bool g_fCanceled = false; + + +/** + * All registered command handlers + */ +static const VBMGCMD g_aCommands[] = +{ + { "internalcommands", VBMG_CMD_INTERNAL, handleInternalCommands, 0 }, + { "list", HELP_CMD_LIST, handleList, 0 }, + { "showvminfo", HELP_CMD_SHOWVMINFO, handleShowVMInfo, 0 }, + { "registervm", HELP_CMD_REGISTERVM, handleRegisterVM, 0 }, + { "unregistervm", HELP_CMD_UNREGISTERVM, handleUnregisterVM, 0 }, + { "clonevm", HELP_CMD_CLONEVM, handleCloneVM, 0 }, + { "movevm", HELP_CMD_MOVEVM, handleMoveVM, 0 }, +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION + { "encryptvm", HELP_CMD_ENCRYPTVM, handleEncryptVM, 0 }, +#endif + { "mediumproperty", HELP_CMD_MEDIUMPROPERTY, handleMediumProperty, 0 }, + { "hdproperty", HELP_CMD_MEDIUMPROPERTY, handleMediumProperty, 0 }, /* backward compatibility */ + { "createmedium", HELP_CMD_CREATEMEDIUM, handleCreateMedium, 0 }, + { "createhd", HELP_CMD_CREATEMEDIUM, handleCreateMedium, 0 }, /* backward compatibility */ + { "createvdi", HELP_CMD_CREATEMEDIUM, handleCreateMedium, 0 }, /* backward compatibility */ + { "modifymedium", HELP_CMD_MODIFYMEDIUM, handleModifyMedium, 0 }, + { "modifyhd", HELP_CMD_MODIFYMEDIUM, handleModifyMedium, 0 }, /* backward compatibility */ + { "modifyvdi", HELP_CMD_MODIFYMEDIUM, handleModifyMedium, 0 }, /* backward compatibility */ + { "clonemedium", HELP_CMD_CLONEMEDIUM, handleCloneMedium, 0 }, + { "clonehd", HELP_CMD_CLONEMEDIUM, handleCloneMedium, 0 }, /* backward compatibility */ + { "clonevdi", HELP_CMD_CLONEMEDIUM, handleCloneMedium, 0 }, /* backward compatibility */ + { "encryptmedium", HELP_CMD_ENCRYPTMEDIUM, handleEncryptMedium, 0 }, + { "checkmediumpwd", HELP_CMD_CHECKMEDIUMPWD, handleCheckMediumPassword, 0 }, + { "createvm", HELP_CMD_CREATEVM, handleCreateVM, 0 }, + { "modifyvm", HELP_CMD_MODIFYVM, handleModifyVM, 0 }, + { "startvm", HELP_CMD_STARTVM, handleStartVM, 0 }, + { "controlvm", HELP_CMD_CONTROLVM, handleControlVM, 0 }, + { "unattended", HELP_CMD_UNATTENDED, handleUnattended, 0 }, + { "discardstate", HELP_CMD_DISCARDSTATE, handleDiscardState, 0 }, + { "adoptstate", HELP_CMD_ADOPTSTATE, handleAdoptState, 0 }, + { "snapshot", HELP_CMD_SNAPSHOT, handleSnapshot, 0 }, + { "closemedium", HELP_CMD_CLOSEMEDIUM, handleCloseMedium, 0 }, + { "storageattach", HELP_CMD_STORAGEATTACH, handleStorageAttach, 0 }, + { "storagectl", HELP_CMD_STORAGECTL, handleStorageController, 0 }, + { "showmediuminfo", HELP_CMD_SHOWMEDIUMINFO, handleShowMediumInfo, 0 }, + { "showhdinfo", HELP_CMD_SHOWMEDIUMINFO, handleShowMediumInfo, 0 }, /* backward compatibility */ + { "showvdiinfo", HELP_CMD_SHOWMEDIUMINFO, handleShowMediumInfo, 0 }, /* backward compatibility */ + { "mediumio", HELP_CMD_MEDIUMIO, handleMediumIO, 0 }, + { "getextradata", HELP_CMD_GETEXTRADATA, handleGetExtraData, 0 }, + { "setextradata", HELP_CMD_SETEXTRADATA, handleSetExtraData, 0 }, + { "setproperty", HELP_CMD_SETPROPERTY, handleSetProperty, 0 }, + { "usbfilter", HELP_CMD_USBFILTER, handleUSBFilter, 0 }, + { "sharedfolder", HELP_CMD_SHAREDFOLDER, handleSharedFolder, 0 }, +#ifdef VBOX_WITH_GUEST_PROPS + { "guestproperty", HELP_CMD_GUESTPROPERTY, handleGuestProperty, 0 }, +#endif +#ifdef VBOX_WITH_GUEST_CONTROL + { "guestcontrol", HELP_CMD_GUESTCONTROL, handleGuestControl, 0 }, +#endif + { "metrics", HELP_CMD_METRICS, handleMetrics, 0 }, + { "import", HELP_CMD_IMPORT, handleImportAppliance, 0 }, + { "export", HELP_CMD_EXPORT, handleExportAppliance, 0 }, + { "signova", HELP_CMD_SIGNOVA, handleSignAppliance, VBMG_CMD_F_NO_COM }, +#ifdef VBOX_WITH_NETFLT + { "hostonlyif", HELP_CMD_HOSTONLYIF, handleHostonlyIf, 0 }, +#endif +#ifdef VBOX_WITH_VMNET + { "hostonlynet", HELP_CMD_HOSTONLYNET, handleHostonlyNet, 0 }, +#endif + { "dhcpserver", HELP_CMD_DHCPSERVER, handleDHCPServer, 0 }, +#ifdef VBOX_WITH_NAT_SERVICE + { "natnetwork", HELP_CMD_NATNETWORK, handleNATNetwork, 0 }, +#endif + { "extpack", HELP_CMD_EXTPACK, handleExtPack, 0 }, + { "bandwidthctl", HELP_CMD_BANDWIDTHCTL, handleBandwidthControl, 0 }, + { "debugvm", HELP_CMD_DEBUGVM, handleDebugVM, 0 }, + { "convertfromraw", HELP_CMD_CONVERTFROMRAW, handleConvertFromRaw, VBMG_CMD_F_NO_COM }, + { "convertdd", HELP_CMD_CONVERTFROMRAW, handleConvertFromRaw, VBMG_CMD_F_NO_COM }, + { "usbdevsource", HELP_CMD_USBDEVSOURCE, handleUSBDevSource, 0 }, + { "cloudprofile", HELP_CMD_CLOUDPROFILE, handleCloudProfile, 0 }, + { "cloud", HELP_CMD_CLOUD, handleCloud, 0 }, +#ifdef VBOX_WITH_UPDATE_AGENT + { "updatecheck", HELP_CMD_UPDATECHECK, handleUpdateCheck, 0 }, +#endif + { "modifynvram", HELP_CMD_MODIFYNVRAM, handleModifyNvram, 0 }, +}; + +/** + * Looks up a command by name. + * + * @returns Pointer to the command structure. + * @param pszCommand Name of the command. + */ +static PCVBMGCMD lookupCommand(const char *pszCommand) +{ + if (pszCommand) + for (uint32_t i = 0; i < RT_ELEMENTS(g_aCommands); i++) + if (!strcmp(g_aCommands[i].pszCommand, pszCommand)) + return &g_aCommands[i]; + return NULL; +} + + +/** + * Signal handler that sets g_fCanceled. + * + * This can be executed on any thread in the process, on Windows it may even be + * a thread dedicated to delivering this signal. Do not doing anything + * unnecessary here. + */ +static void showProgressSignalHandler(int iSignal) RT_NOTHROW_DEF +{ + NOREF(iSignal); + ASMAtomicWriteBool(&g_fCanceled, true); +} + +/** + * Print out progress on the console. + * + * This runs the main event queue every now and then to prevent piling up + * unhandled things (which doesn't cause real problems, just makes things + * react a little slower than in the ideal case). + */ +HRESULT showProgress(ComPtr<IProgress> progress, uint32_t fFlags) +{ + using namespace com; + HRESULT hrc; + + AssertReturn(progress.isNotNull(), E_FAIL); + + /* grandfather the old callers */ + if (g_fDetailedProgress) + fFlags = SHOW_PROGRESS_DETAILS; + + const bool fDetailed = RT_BOOL(fFlags & SHOW_PROGRESS_DETAILS); + const bool fQuiet = !RT_BOOL(fFlags & (SHOW_PROGRESS | SHOW_PROGRESS_DETAILS)); + + + BOOL fCompleted = FALSE; + ULONG ulCurrentPercent = 0; + ULONG ulLastPercent = 0; + + ULONG ulLastOperationPercent = (ULONG)-1; + + ULONG ulLastOperation = (ULONG)-1; + Bstr bstrOperationDescription; + + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + + ULONG cOperations = 1; + hrc = progress->COMGETTER(OperationCount)(&cOperations); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdErr, VBoxManage::tr("Progress object failure: %Rhrc\n"), hrc); + RTStrmFlush(g_pStdErr); + return hrc; + } + + /* + * Note: Outputting the progress info to stderr (g_pStdErr) is intentional + * to not get intermixed with other (raw) stdout data which might get + * written in the meanwhile. + */ + + if (fFlags & SHOW_PROGRESS_DESC) + { + com::Bstr bstrDescription; + hrc = progress->COMGETTER(Description(bstrDescription.asOutParam())); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdErr, VBoxManage::tr("Failed to get progress description: %Rhrc\n"), hrc); + return hrc; + } + + const char *pcszDescSep; + if (fDetailed) /* multiline output */ + pcszDescSep = "\n"; + else /* continues on the same line */ + pcszDescSep = ": "; + + RTStrmPrintf(g_pStdErr, "%ls%s", bstrDescription.raw(), pcszDescSep); + RTStrmFlush(g_pStdErr); + } + + if (!fQuiet && !fDetailed) + { + RTStrmPrintf(g_pStdErr, "0%%..."); + RTStrmFlush(g_pStdErr); + } + + /* setup signal handling if cancelable */ + bool fCanceledAlready = false; + BOOL fCancelable; + hrc = progress->COMGETTER(Cancelable)(&fCancelable); + if (FAILED(hrc)) + fCancelable = FALSE; + if (fCancelable) + { + signal(SIGINT, showProgressSignalHandler); + signal(SIGTERM, showProgressSignalHandler); +#ifdef SIGBREAK + signal(SIGBREAK, showProgressSignalHandler); +#endif + } + + hrc = progress->COMGETTER(Completed(&fCompleted)); + while (SUCCEEDED(hrc)) + { + progress->COMGETTER(Percent(&ulCurrentPercent)); + + if (fDetailed) + { + ULONG ulOperation = 1; + hrc = progress->COMGETTER(Operation)(&ulOperation); + if (FAILED(hrc)) + break; + ULONG ulCurrentOperationPercent = 0; + hrc = progress->COMGETTER(OperationPercent(&ulCurrentOperationPercent)); + if (FAILED(hrc)) + break; + + if (ulLastOperation != ulOperation) + { + hrc = progress->COMGETTER(OperationDescription(bstrOperationDescription.asOutParam())); + if (FAILED(hrc)) + break; + ulLastPercent = (ULONG)-1; // force print + ulLastOperation = ulOperation; + } + + if ( ulCurrentPercent != ulLastPercent + || ulCurrentOperationPercent != ulLastOperationPercent + ) + { + LONG lSecsRem = 0; + progress->COMGETTER(TimeRemaining)(&lSecsRem); + + RTStrmPrintf(g_pStdErr, VBoxManage::tr("(%u/%u) %ls %02u%% => %02u%% (%d s remaining)\n"), ulOperation + 1, cOperations, + bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent, lSecsRem); + ulLastPercent = ulCurrentPercent; + ulLastOperationPercent = ulCurrentOperationPercent; + } + } + else if (!fQuiet) + { + /* did we cross a 10% mark? */ + if (ulCurrentPercent / 10 > ulLastPercent / 10) + { + /* make sure to also print out missed steps */ + for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10) + { + if (curVal < 100) + { + RTStrmPrintf(g_pStdErr, "%u%%...", curVal); + RTStrmFlush(g_pStdErr); + } + } + ulLastPercent = (ulCurrentPercent / 10) * 10; + } + } + if (fCompleted) + break; + + /* process async cancelation */ + if (g_fCanceled && !fCanceledAlready) + { + hrc = progress->Cancel(); + if (SUCCEEDED(hrc)) + fCanceledAlready = true; + else + g_fCanceled = false; + } + + /* make sure the loop is not too tight */ + progress->WaitForCompletion(100); + + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + hrc = progress->COMGETTER(Completed(&fCompleted)); + } + + /* undo signal handling */ + if (fCancelable) + { + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +# ifdef SIGBREAK + signal(SIGBREAK, SIG_DFL); +# endif + } + + /* complete the line. */ + LONG iRc = E_FAIL; + hrc = progress->COMGETTER(ResultCode)(&iRc); + if (SUCCEEDED(hrc)) + { + /* async operation completed successfully */ + if (SUCCEEDED(iRc)) + { + if (!fDetailed) + { + if (fFlags == SHOW_PROGRESS_DESC) + RTStrmPrintf(g_pStdErr, "ok\n"); + else if (!fQuiet) + RTStrmPrintf(g_pStdErr, "100%%\n"); + } + } + else if (g_fCanceled) + RTStrmPrintf(g_pStdErr, VBoxManage::tr("CANCELED\n")); + else + { + if (fDetailed) + RTStrmPrintf(g_pStdErr, VBoxManage::tr("Progress state: %Rhrc\n"), iRc); + else if (fFlags != SHOW_PROGRESS_NONE) + RTStrmPrintf(g_pStdErr, "%Rhrc\n", iRc); + } + hrc = iRc; + } + else + { + if (!fDetailed) + RTStrmPrintf(g_pStdErr, "\n"); + RTStrmPrintf(g_pStdErr, VBoxManage::tr("Progress object failure: %Rhrc\n"), hrc); + } + RTStrmFlush(g_pStdErr); + return hrc; +} + + +void setBuiltInHelpLanguage(const char *pszLang) +{ +#ifdef VBOX_WITH_VBOXMANAGE_NLS + if (pszLang == NULL || pszLang[0] == '\0' || (pszLang[0] == 'C' && pszLang[1] == '\0')) + pszLang = "en_US"; + + /* find language entry matching exactly pszLang */ + PCHELP_LANG_ENTRY_T pHelpLangEntry = NULL; + for (uint32_t i = 0; i < g_cHelpLangEntries; i++) + { + if (strcmp(g_aHelpLangEntries[i].pszLang, pszLang) == 0) + { + pHelpLangEntry = &g_aHelpLangEntries[i]; + break; + } + } + + /* find first entry containing language specified if pszLang contains only language */ + if (pHelpLangEntry == NULL) + { + size_t const cchLang = strlen(pszLang); + for (uint32_t i = 0; i < g_cHelpLangEntries; i++) + { + if ( cchLang < g_aHelpLangEntries[i].cchLang + && memcmp(g_aHelpLangEntries[i].pszLang, pszLang, cchLang) == 0) + { + pHelpLangEntry = &g_aHelpLangEntries[i]; + break; + } + } + } + + /* set to en_US (i.e. untranslated) if not found */ + if (pHelpLangEntry == NULL) + pHelpLangEntry = &g_aHelpLangEntries[0]; + + ASMAtomicWritePtr(&g_pHelpLangEntry, pHelpLangEntry); +#else + NOREF(pszLang); +#endif +} + + +int main(int argc, char *argv[]) +{ + /* + * Before we do anything, init the runtime without loading + * the support driver. + */ + int vrc = RTR3InitExe(argc, &argv, 0); + if (RT_FAILURE(vrc)) + return RTMsgInitFailure(vrc); +#if defined(RT_OS_WINDOWS) + ATL::CComModule _Module; /* Required internally by ATL (constructor records instance in global variable). */ +#endif + +#ifdef VBOX_WITH_VBOXMANAGE_NLS + /* + * Initialize the translator and associated fun. + */ + util::InitAutoLockSystem(); + ComObjPtr<VBoxEventListenerImpl> ptrEventListner; + PTRCOMPONENT pTrComponent = NULL; + VirtualBoxTranslator *pTranslator = VirtualBoxTranslator::instance(); + if (pTranslator != NULL) + { + char szNlsPath[RTPATH_MAX]; + vrc = RTPathAppPrivateNoArch(szNlsPath, sizeof(szNlsPath)); + if (RT_SUCCESS(vrc)) + vrc = RTPathAppend(szNlsPath, sizeof(szNlsPath), "nls" RTPATH_SLASH_STR "VBoxManageNls"); + if (RT_SUCCESS(vrc)) + { + vrc = pTranslator->registerTranslation(szNlsPath, true, &pTrComponent); + if (RT_SUCCESS(vrc)) + { + vrc = pTranslator->i_loadLanguage(NULL); + if (RT_SUCCESS(vrc)) + { + com::Utf8Str strLang = pTranslator->language(); + setBuiltInHelpLanguage(strLang.c_str()); + } + else + RTMsgWarning("Load language failed: %Rrc\n", vrc); + } + else + RTMsgWarning("Register translation failed: %Rrc\n", vrc); + } + else + RTMsgWarning("Path constructing failed: %Rrc\n", vrc); + } +#endif + + /* + * Parse the global options + */ + bool fShowLogo = false; + bool fShowHelp = false; + int iCmd = 1; + int iCmdArg; + const char *pszSettingsPw = NULL; + const char *pszSettingsPwFile = NULL; + int cResponseFileArgs = 0; + char **papszResponseFileArgs = NULL; + char **papszNewArgv = NULL; + + for (int i = 1; i < argc || argc <= iCmd; i++) + { + if ( argc <= iCmd + || !strcmp(argv[i], "help") + || !strcmp(argv[i], "--help") + || !strcmp(argv[i], "-?") + || !strcmp(argv[i], "-h") + || !strcmp(argv[i], "-help")) + { + if (i >= argc - 1) + { + showLogo(g_pStdOut); + printUsage(g_pStdOut); + return 0; + } + fShowLogo = true; + fShowHelp = true; + iCmd++; + continue; + } + + if ( !strcmp(argv[i], "-V") + || !strcmp(argv[i], "--version") + || !strcmp(argv[i], "-v") /* deprecated */ + || !strcmp(argv[i], "-version") /* deprecated */ + || !strcmp(argv[i], "-Version") /* deprecated */) + { + /* Print version number, and do nothing else. */ + RTPrintf("%sr%u\n", VBOX_VERSION_STRING, RTBldCfgRevision()); + return 0; + } + if (!strcmp(argv[i], "--dump-build-type")) + { + /* Print the build type, and do nothing else. (Used by ValKit to detect build type.) */ + RTPrintf("%s\n", RTBldCfgType()); + return 0; + } + + if ( !strcmp(argv[i], "--dumpopts") + || !strcmp(argv[i], "-dumpopts") /* deprecated */) + { + /* Special option to dump really all commands, + * even the ones not understood on this platform. */ + printUsage(g_pStdOut); + return 0; + } + + if ( !strcmp(argv[i], "--nologo") + || !strcmp(argv[i], "-q") + || !strcmp(argv[i], "-nologo") /* deprecated */) + { + /* suppress the logo */ + fShowLogo = false; + iCmd++; + } + else if ( !strcmp(argv[i], "--detailed-progress") + || !strcmp(argv[i], "-d")) + { + /* detailed progress report */ + g_fDetailedProgress = true; + iCmd++; + } + else if (!strcmp(argv[i], "--settingspw")) + { + if (i >= argc - 1) + return RTMsgErrorExit(RTEXITCODE_FAILURE, VBoxManage::tr("Password expected")); + /* password for certain settings */ + pszSettingsPw = argv[i + 1]; + iCmd += 2; + } + else if (!strcmp(argv[i], "--settingspwfile")) + { + if (i >= argc-1) + return RTMsgErrorExit(RTEXITCODE_FAILURE, VBoxManage::tr("No password file specified")); + pszSettingsPwFile = argv[i+1]; + iCmd += 2; + } + else if (argv[i][0] == '@') + { + if (papszResponseFileArgs) + return RTMsgErrorExitFailure(VBoxManage::tr("Only one response file allowed")); + + /* Load response file, making sure it's valid UTF-8. */ + char *pszResponseFile; + size_t cbResponseFile; + vrc = RTFileReadAllEx(&argv[i][1], 0, RTFOFF_MAX, RTFILE_RDALL_O_DENY_NONE | RTFILE_RDALL_F_TRAILING_ZERO_BYTE, + (void **)&pszResponseFile, &cbResponseFile); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(VBoxManage::tr("Error reading response file '%s': %Rrc"), &argv[i][1], vrc); + vrc = RTStrValidateEncoding(pszResponseFile); + if (RT_FAILURE(vrc)) + { + RTFileReadAllFree(pszResponseFile, cbResponseFile); + return RTMsgErrorExitFailure(VBoxManage::tr("Invalid response file ('%s') encoding: %Rrc"), &argv[i][1], vrc); + } + + /* Parse it. */ + vrc = RTGetOptArgvFromString(&papszResponseFileArgs, &cResponseFileArgs, pszResponseFile, + RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, NULL); + RTFileReadAllFree(pszResponseFile, cbResponseFile); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(VBoxManage::tr("Failed to parse response file '%s' (bourne shell style): %Rrc"), &argv[i][1], vrc); + + /* Construct new argv+argc with the response file arguments inserted. */ + int cNewArgs = argc + cResponseFileArgs; + papszNewArgv = (char **)RTMemAllocZ((cNewArgs + 2) * sizeof(papszNewArgv[0])); + if (!papszNewArgv) + return RTMsgErrorExitFailure(VBoxManage::tr("out of memory")); + memcpy(&papszNewArgv[0], &argv[0], sizeof(argv[0]) * (i + 1)); + memcpy(&papszNewArgv[i + 1], papszResponseFileArgs, sizeof(argv[0]) * cResponseFileArgs); + memcpy(&papszNewArgv[i + 1 + cResponseFileArgs], &argv[i + 1], sizeof(argv[0]) * (argc - i - 1 + 1)); + argv = papszNewArgv; + argc = argc + cResponseFileArgs; + + iCmd++; + } + else + break; + } + + iCmdArg = iCmd + 1; + + /* + * Show the logo and lookup the command and deal with fShowHelp = true. + */ + if (fShowLogo) + showLogo(g_pStdOut); + + PCVBMGCMD pCmd = lookupCommand(argv[iCmd]); + if (pCmd && pCmd->enmCmdHelp != VBMG_CMD_INTERNAL) + setCurrentCommand(pCmd->enmCmdHelp); + + if ( pCmd + && ( fShowHelp + || argc - iCmdArg == 0)) + { + if (pCmd->enmCmdHelp == VBMG_CMD_INTERNAL) + printUsageInternalCmds(g_pStdOut); + else if (fShowHelp) + printHelp(g_pStdOut); + else + printUsage(g_pStdOut); + return RTEXITCODE_FAILURE; /* error */ + } + if (!pCmd) + { + if (!strcmp(argv[iCmd], "commands")) + { + RTPrintf(VBoxManage::tr("commands:\n")); + for (unsigned i = 0; i < RT_ELEMENTS(g_aCommands); i++) + if ( i == 0 /* skip backwards compatibility entries */ + || (g_aCommands[i].enmCmdHelp != g_aCommands[i - 1].enmCmdHelp)) + RTPrintf(" %s\n", g_aCommands[i].pszCommand); + return RTEXITCODE_SUCCESS; + } + return errorSyntax(VBoxManage::tr("Invalid command '%s'"), argv[iCmd]); + } + + RTEXITCODE rcExit; + if (!(pCmd->fFlags & VBMG_CMD_F_NO_COM)) + { + /* + * Initialize COM. + */ + using namespace com; + HRESULT hrc = com::Initialize(); + if (FAILED(hrc)) + { +# ifdef VBOX_WITH_XPCOM + if (hrc == NS_ERROR_FILE_ACCESS_DENIED) + { + char szHome[RTPATH_MAX] = ""; + com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome)); + return RTMsgErrorExit(RTEXITCODE_FAILURE, + VBoxManage::tr("Failed to initialize COM because the global settings directory '%s' is not accessible!"), szHome); + } +# endif + return RTMsgErrorExit(RTEXITCODE_FAILURE, VBoxManage::tr("Failed to initialize COM! (hrc=%Rhrc)"), hrc); + } + + + /* + * Get the remote VirtualBox object and create a local session object. + */ + rcExit = RTEXITCODE_FAILURE; + ComPtr<IVirtualBoxClient> virtualBoxClient; + ComPtr<IVirtualBox> virtualBox; + hrc = virtualBoxClient.createInprocObject(CLSID_VirtualBoxClient); + if (SUCCEEDED(hrc)) + hrc = virtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam()); + if (SUCCEEDED(hrc)) + { +#ifdef VBOX_WITH_VBOXMANAGE_NLS + /* Load language settings from IVirtualBox. */ + if (pTranslator != NULL) + { + HRESULT hrc1 = pTranslator->loadLanguage(virtualBox); + if (SUCCEEDED(hrc1)) + { + com::Utf8Str strLang = pTranslator->language(); + setBuiltInHelpLanguage(strLang.c_str()); + } + else + RTMsgWarning("Failed to load API language: %Rhrc", hrc1); + + /* VirtualBox language events registration. */ + ComPtr<IEventSource> pES; + hrc1 = virtualBox->COMGETTER(EventSource)(pES.asOutParam()); + if (SUCCEEDED(hrc1)) + { + hrc1 = ptrEventListner.createObject(); + if (SUCCEEDED(hrc1)) + hrc1 = ptrEventListner->init(new VBoxEventListener()); + if (SUCCEEDED(hrc1)) + { + com::SafeArray<VBoxEventType_T> eventTypes; + eventTypes.push_back(VBoxEventType_OnLanguageChanged); + hrc1 = pES->RegisterListener(ptrEventListner, ComSafeArrayAsInParam(eventTypes), true); + } + if (FAILED(hrc1)) + { + ptrEventListner.setNull(); + RTMsgWarning("Failed to register event listener: %Rhrc", hrc1); + } + } + } +#endif + + ComPtr<ISession> session; + hrc = session.createInprocObject(CLSID_Session); + if (SUCCEEDED(hrc)) + { + /* Session secret. */ + if (pszSettingsPw) + CHECK_ERROR2I_STMT(virtualBox, SetSettingsSecret(Bstr(pszSettingsPw).raw()), rcExit = RTEXITCODE_FAILURE); + else if (pszSettingsPwFile) + rcExit = settingsPasswordFile(virtualBox, pszSettingsPwFile); + else + rcExit = RTEXITCODE_SUCCESS; + if (rcExit == RTEXITCODE_SUCCESS) + { + /* + * Call the handler. + */ + HandlerArg handlerArg = { argc - iCmdArg, &argv[iCmdArg], virtualBox, session }; + rcExit = pCmd->pfnHandler(&handlerArg); + + /* Although all handlers should always close the session if they open it, + * we do it here just in case if some of the handlers contains a bug -- + * leaving the direct session not closed will turn the machine state to + * Aborted which may have unwanted side effects like killing the saved + * state file (if the machine was in the Saved state before). */ + session->UnlockMachine(); + } + + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + } + else + { + com::ErrorInfo info; + RTMsgError(VBoxManage::tr("Failed to create a session object!")); + if (!info.isFullAvailable() && !info.isBasicAvailable()) + com::GluePrintRCMessage(hrc); + else + com::GluePrintErrorInfo(info); + } + } + else + { + com::ErrorInfo info; + RTMsgError(VBoxManage::tr("Failed to create the VirtualBox object!")); + if (!info.isFullAvailable() && !info.isBasicAvailable()) + { + com::GluePrintRCMessage(hrc); + RTMsgError(VBoxManage::tr("Most likely, the VirtualBox COM server is not running or failed to start.")); + } + else + com::GluePrintErrorInfo(info); + } + +#ifdef VBOX_WITH_VBOXMANAGE_NLS + /* VirtualBox event callback unregistration. */ + if (ptrEventListner.isNotNull()) + { + ComPtr<IEventSource> pES; + HRESULT hrc1 = virtualBox->COMGETTER(EventSource)(pES.asOutParam()); + if (pES.isNotNull()) + { + hrc1 = pES->UnregisterListener(ptrEventListner); + if (FAILED(hrc1)) + LogRel(("Failed to unregister listener, %Rhrc", hrc1)); + } + ptrEventListner.setNull(); + } +#endif + /* + * Terminate COM, make sure the virtualBox object has been released. + */ + virtualBox.setNull(); + virtualBoxClient.setNull(); + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + com::Shutdown(); + } + else + { + /* + * The command needs no COM. + */ + HandlerArg handlerArg; + handlerArg.argc = argc - iCmdArg; + handlerArg.argv = &argv[iCmdArg]; + rcExit = pCmd->pfnHandler(&handlerArg); + } + +#ifdef VBOX_WITH_VBOXMANAGE_NLS + if (pTranslator != NULL) + { + pTranslator->release(); + pTranslator = NULL; + pTrComponent = NULL; + } +#endif + + if (papszResponseFileArgs) + { + RTGetOptArgvFree(papszResponseFileArgs); + RTMemFree(papszNewArgv); + } + + return rcExit; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManage.h b/src/VBox/Frontends/VBoxManage/VBoxManage.h new file mode 100644 index 00000000..35ab4a15 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManage.h @@ -0,0 +1,313 @@ +/* $Id: VBoxManage.h $ */ +/** @file + * VBoxManage - VirtualBox command-line interface, internal header file. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_VBoxManage_VBoxManage_h +#define VBOX_INCLUDED_SRC_VBoxManage_VBoxManage_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/com.h> +#include <VBox/com/ptr.h> +#include <VBox/com/VirtualBox.h> +#include <VBox/com/string.h> +#include <VBox/com/array.h> + +#include <iprt/types.h> +#include <iprt/message.h> +#include <iprt/stream.h> +#include <iprt/getopt.h> + +#include "VBoxManageBuiltInHelp.h" +#include "PasswordInput.h" + +#ifdef VBOX_WITH_VBOXMANAGE_NLS +# include "VirtualBoxTranslator.h" +#endif + + +//////////////////////////////////////////////////////////////////////////////// +// +// definitions +// +//////////////////////////////////////////////////////////////////////////////// + +/** + * This defines a a_CtxName::tr function that gives the translator context as + * well as providing a shorter way to call VirtualBoxTranslator::translate. + */ +#ifdef VBOX_WITH_VBOXMANAGE_NLS +# define DECLARE_TRANSLATION_CONTEXT(a_CtxName) \ +struct a_CtxName \ +{ \ + static const char *tr(const char *pszSource, const char *pszComment = NULL, const size_t uNum = ~(size_t)0) \ + { \ + return VirtualBoxTranslator::translate(NULL, #a_CtxName, pszSource, pszComment, uNum); \ + } \ +} +#else +# define DECLARE_TRANSLATION_CONTEXT(a_CtxName) \ +struct a_CtxName \ +{ \ + static const char *tr(const char *pszSource, const char *pszComment = NULL, const size_t uNum = ~(size_t)0) \ + { \ + RT_NOREF(pszComment, uNum); \ + return pszSource; \ + } \ +} +#endif + +/** + * Defines an option with two variants, producing two RTGETOPTDEF entries. + * + * This is mainly for replacing character-soup option names like + * --natlocalhostreachable and --biossystemtimeoffset with more easily parsed + * ones, like --nat-localhost-reachable and --bios-system-time-offset, without + * removing the legacy name. + */ +#define OPT2(a_pszWordDashWord, a_pszWordSoup, a_chOptOrValue, a_fFlags) \ + { a_pszWordDashWord, a_chOptOrValue, a_fFlags }, \ + { a_pszWordSoup, a_chOptOrValue, a_fFlags } + +/** A single option variant of OPT2 for better looking tables. */ +#define OPT1(a_pszOption, a_chOptOrValue, a_fFlags) \ + { a_pszOption, a_chOptOrValue, a_fFlags } + + +/** command handler argument */ +struct HandlerArg +{ + int argc; + char **argv; + + ComPtr<IVirtualBox> virtualBox; + ComPtr<ISession> session; +}; + + +/** showVMInfo details */ +typedef enum +{ + VMINFO_NONE = 0, + VMINFO_STANDARD = 1, /**< standard details */ + VMINFO_FULL = 2, /**< both */ + VMINFO_MACHINEREADABLE = 3, /**< both, and make it machine readable */ + VMINFO_COMPACT = 4 +} VMINFO_DETAILS; + + +//////////////////////////////////////////////////////////////////////////////// +// +// global variables +// +//////////////////////////////////////////////////////////////////////////////// + +extern bool g_fDetailedProgress; // in VBoxManage.cpp + + +//////////////////////////////////////////////////////////////////////////////// +// +// prototypes +// +//////////////////////////////////////////////////////////////////////////////// + +/* VBoxManageHelp.cpp */ +void setCurrentCommand(enum HELP_CMD_VBOXMANAGE enmCommand); +void setCurrentSubcommand(uint64_t fCurSubcommandScope); + +void printUsage(PRTSTREAM pStrm); +void printHelp(PRTSTREAM pStrm); +RTEXITCODE errorNoSubcommand(void); +RTEXITCODE errorUnknownSubcommand(const char *pszSubCmd); +RTEXITCODE errorTooManyParameters(char **papszArgs); +RTEXITCODE errorGetOpt(int rcGetOpt, union RTGETOPTUNION const *pValueUnion); +RTEXITCODE errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion); +RTEXITCODE errorSyntax(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2); +RTEXITCODE errorSyntaxV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0); +HRESULT errorSyntaxHr(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2); +RTEXITCODE errorArgument(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2); +HRESULT errorArgumentHr(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2); + +# define SHOW_PROGRESS_NONE 0 +# define SHOW_PROGRESS_DESC RT_BIT_32(0) +# define SHOW_PROGRESS RT_BIT_32(1) +# define SHOW_PROGRESS_DETAILS RT_BIT_32(2) +HRESULT showProgress(ComPtr<IProgress> progress, uint32_t fFlags = SHOW_PROGRESS); + +/* VBoxManage.cpp */ +void showLogo(PRTSTREAM pStrm); + +/* VBoxInternalManage.cpp */ +DECLHIDDEN(void) printUsageInternalCmds(PRTSTREAM pStrm); +RTEXITCODE handleInternalCommands(HandlerArg *a); + +/* VBoxManageControlVM.cpp */ +RTEXITCODE handleControlVM(HandlerArg *a); + +/* VBoxManageModifyVM.cpp */ +void parseGroups(const char *pcszGroups, com::SafeArray<BSTR> *pGroups); +#ifdef VBOX_WITH_RECORDING +int parseScreens(const char *pcszScreens, com::SafeArray<BOOL> *pScreens); +#endif +RTEXITCODE handleModifyVM(HandlerArg *a); + +/* VBoxManageDebugVM.cpp */ +RTEXITCODE handleDebugVM(HandlerArg *a); + +/* VBoxManageGuestProp.cpp */ +RTEXITCODE handleGuestProperty(HandlerArg *a); + +/* VBoxManageGuestCtrl.cpp */ +RTEXITCODE handleGuestControl(HandlerArg *a); + +/* VBoxManageVMInfo.cpp */ +HRESULT showSnapshots(ComPtr<ISnapshot> &rootSnapshot, + ComPtr<ISnapshot> ¤tSnapshot, + VMINFO_DETAILS details, + const com::Utf8Str &prefix = "", + int level = 0); +RTEXITCODE handleShowVMInfo(HandlerArg *a); +HRESULT showVMInfo(ComPtr<IVirtualBox> pVirtualBox, + ComPtr<IMachine> pMachine, + ComPtr<ISession> pSession, + VMINFO_DETAILS details = VMINFO_NONE); +const char *machineStateToName(MachineState_T machineState, bool fShort); +HRESULT showBandwidthGroups(ComPtr<IBandwidthControl> &bwCtrl, + VMINFO_DETAILS details); +void outputMachineReadableString(const char *pszName, const char *pszValue, bool fQuoteName = false, bool fNewline = true); +void outputMachineReadableString(const char *pszName, com::Bstr const *pbstrValue, bool fQuoteName = false, bool fNewline = true); +void outputMachineReadableStringWithFmtName(const char *pszValue, bool fQuoteName, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(3, 4); +void outputMachineReadableStringWithFmtName(com::Bstr const *pbstrValue, bool fQuoteName, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(3, 4); +void outputMachineReadableBool(const char *pszName, BOOL const *pfValue); +void outputMachineReadableBool(const char *pszName, bool const *pfValue); +void outputMachineReadableULong(const char *pszName, ULONG *uValue); +void outputMachineReadableLong64(const char *pszName, LONG64 *uValue); + +/* VBoxManageList.cpp */ +RTEXITCODE handleList(HandlerArg *a); + +/* VBoxManageMetrics.cpp */ +RTEXITCODE handleMetrics(HandlerArg *a); + +/* VBoxManageMisc.cpp */ +RTEXITCODE handleRegisterVM(HandlerArg *a); +RTEXITCODE handleUnregisterVM(HandlerArg *a); +RTEXITCODE handleCreateVM(HandlerArg *a); +RTEXITCODE handleCloneVM(HandlerArg *a); +RTEXITCODE handleStartVM(HandlerArg *a); +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION +RTEXITCODE handleEncryptVM(HandlerArg *a); +#endif +RTEXITCODE handleDiscardState(HandlerArg *a); +RTEXITCODE handleAdoptState(HandlerArg *a); +RTEXITCODE handleGetExtraData(HandlerArg *a); +RTEXITCODE handleSetExtraData(HandlerArg *a); +RTEXITCODE handleSetProperty(HandlerArg *a); +RTEXITCODE handleSharedFolder(HandlerArg *a); +RTEXITCODE handleExtPack(HandlerArg *a); +RTEXITCODE handleUnattended(HandlerArg *a); +RTEXITCODE handleMoveVM(HandlerArg *a); +RTEXITCODE handleCloudProfile(HandlerArg *a); + +/* VBoxManageDisk.cpp */ +HRESULT openMedium(HandlerArg *a, const char *pszFilenameOrUuid, + DeviceType_T enmDevType, AccessMode_T enmAccessMode, + ComPtr<IMedium> &pMedium, bool fForceNewUuidOnOpen, + bool fSilent); +RTEXITCODE handleCreateMedium(HandlerArg *a); +RTEXITCODE handleModifyMedium(HandlerArg *a); +RTEXITCODE handleCloneMedium(HandlerArg *a); +RTEXITCODE handleMediumProperty(HandlerArg *a); +RTEXITCODE handleEncryptMedium(HandlerArg *a); +RTEXITCODE handleCheckMediumPassword(HandlerArg *a); +RTEXITCODE handleConvertFromRaw(HandlerArg *a); +HRESULT showMediumInfo(const ComPtr<IVirtualBox> &pVirtualBox, + const ComPtr<IMedium> &pMedium, + const char *pszParentUUID, + bool fOptLong); +RTEXITCODE handleShowMediumInfo(HandlerArg *a); +RTEXITCODE handleCloseMedium(HandlerArg *a); +RTEXITCODE handleMediumIO(HandlerArg *a); +int parseMediumType(const char *psz, MediumType_T *penmMediumType); +int parseBool(const char *psz, bool *pb); + +/* VBoxManageStorageController.cpp */ +RTEXITCODE handleStorageAttach(HandlerArg *a); +RTEXITCODE handleStorageController(HandlerArg *a); + +// VBoxManageAppliance.cpp +RTEXITCODE handleImportAppliance(HandlerArg *a); +RTEXITCODE handleExportAppliance(HandlerArg *a); +RTEXITCODE handleSignAppliance(HandlerArg *a); + +// VBoxManageSnapshot.cpp +RTEXITCODE handleSnapshot(HandlerArg *a); + +/* VBoxManageUSB.cpp */ +RTEXITCODE handleUSBFilter(HandlerArg *a); +RTEXITCODE handleUSBDevSource(HandlerArg *a); + +/* VBoxManageHostonly.cpp */ +RTEXITCODE handleHostonlyIf(HandlerArg *a); +#ifdef VBOX_WITH_VMNET +RTEXITCODE handleHostonlyNet(HandlerArg *a); +#endif /* VBOX_WITH_VMNET */ + +/* VBoxManageDHCPServer.cpp */ +RTEXITCODE handleDHCPServer(HandlerArg *a); + +/* VBoxManageNATNetwork.cpp */ +RTEXITCODE handleNATNetwork(HandlerArg *a); +RTEXITCODE listNATNetworks(bool fLong, bool fSorted, + const ComPtr<IVirtualBox> &pVirtualBox); + +/* VBoxManageBandwidthControl.cpp */ +RTEXITCODE handleBandwidthControl(HandlerArg *a); + +/* VBoxManageCloud.cpp */ +RTEXITCODE handleCloud(HandlerArg *a); + +/* VBoxManageCloudMachine.cpp */ +RTEXITCODE handleCloudMachine(HandlerArg *a, int iFirst, + const char *pcszProviderName, + const char *pcszProfileName); +RTEXITCODE listCloudMachines(HandlerArg *a, int iFirst, + const char *pcszProviderName, + const char *pcszProfileName); +RTEXITCODE handleCloudShowVMInfo(HandlerArg *a, int iFirst, + const char *pcszProviderName, + const char *pcszProfileName); + +#ifdef VBOX_WITH_UPDATE_AGENT +/* VBoxManageUpdateCheck.cpp */ +RTEXITCODE handleUpdateCheck(HandlerArg *a); +#endif + +/* VBoxManageModifyNvram.cpp */ +RTEXITCODE handleModifyNvram(HandlerArg *a); + +#endif /* !VBOX_INCLUDED_SRC_VBoxManage_VBoxManage_h */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManage.rc b/src/VBox/Frontends/VBoxManage/VBoxManage.rc new file mode 100644 index 00000000..e2aa3172 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManage.rc @@ -0,0 +1,61 @@ +/* $Id: VBoxManage.rc $ */ +/** @file + * VBoxManage - Resource file containing version info and icon. + */ + +/* + * Copyright (C) 2015-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include <windows.h> +#include <VBox/version.h> + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VBOX_RC_FILE_VERSION + PRODUCTVERSION VBOX_RC_FILE_VERSION + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS VBOX_RC_FILE_FLAGS + FILEOS VBOX_RC_FILE_OS + FILETYPE VBOX_RC_TYPE_APP + FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" // Lang=US English, CharSet=Unicode + BEGIN + VALUE "FileDescription", "VirtualBox Command Line Tool\0" + VALUE "InternalName", "VBoxManage\0" + VALUE "OriginalFilename", "VBoxManage.exe\0" + VALUE "CompanyName", VBOX_RC_COMPANY_NAME + VALUE "FileVersion", VBOX_RC_FILE_VERSION_STR + VALUE "LegalCopyright", VBOX_RC_LEGAL_COPYRIGHT + VALUE "ProductName", VBOX_RC_PRODUCT_NAME_STR + VALUE "ProductVersion", VBOX_RC_PRODUCT_VERSION_STR + VBOX_RC_MORE_STRINGS + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp new file mode 100644 index 00000000..fb44a061 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp @@ -0,0 +1,2916 @@ +/* $Id: VBoxManageAppliance.cpp $ */ +/** @file + * VBoxManage - The appliance-related commands. + */ + +/* + * Copyright (C) 2009-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> +#include <VBox/log.h> +#include <VBox/param.h> + +#include <VBox/version.h> + +#include <list> +#include <map> + +#include <iprt/getopt.h> +#include <iprt/ctype.h> +#include <iprt/path.h> +#include <iprt/file.h> +#include <iprt/err.h> +#include <iprt/zip.h> +#include <iprt/stream.h> +#include <iprt/vfs.h> +#include <iprt/manifest.h> +#include <iprt/crypto/digest.h> +#include <iprt/crypto/x509.h> +#include <iprt/crypto/pkcs7.h> +#include <iprt/crypto/store.h> +#include <iprt/crypto/spc.h> +#include <iprt/crypto/key.h> +#include <iprt/crypto/pkix.h> + + + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Appliance); + + +// funcs +/////////////////////////////////////////////////////////////////////////////// + +typedef std::map<Utf8Str, Utf8Str> ArgsMap; // pairs of strings like "vmname" => "newvmname" +typedef std::map<uint32_t, ArgsMap> ArgsMapsMap; // map of maps, one for each virtual system, sorted by index + +typedef std::map<uint32_t, bool> IgnoresMap; // pairs of numeric description entry indices +typedef std::map<uint32_t, IgnoresMap> IgnoresMapsMap; // map of maps, one for each virtual system, sorted by index + +static bool findArgValue(Utf8Str &strOut, + ArgsMap *pmapArgs, + const Utf8Str &strKey) +{ + if (pmapArgs) + { + ArgsMap::iterator it; + it = pmapArgs->find(strKey); + if (it != pmapArgs->end()) + { + strOut = it->second; + pmapArgs->erase(it); + return true; + } + } + + return false; +} + +static int parseImportOptions(const char *psz, com::SafeArray<ImportOptions_T> *options) +{ + int vrc = VINF_SUCCESS; + while (psz && *psz && RT_SUCCESS(vrc)) + { + size_t len; + const char *pszComma = strchr(psz, ','); + if (pszComma) + len = pszComma - psz; + else + len = strlen(psz); + if (len > 0) + { + if (!RTStrNICmp(psz, "KeepAllMACs", len)) + options->push_back(ImportOptions_KeepAllMACs); + else if (!RTStrNICmp(psz, "KeepNATMACs", len)) + options->push_back(ImportOptions_KeepNATMACs); + else if (!RTStrNICmp(psz, "ImportToVDI", len)) + options->push_back(ImportOptions_ImportToVDI); + else + vrc = VERR_PARSE_ERROR; + } + if (pszComma) + psz += len + 1; + else + psz += len; + } + + return vrc; +} + +/** + * Helper routine to parse the ExtraData Utf8Str for a storage controller's + * value or channel value. + * + * @param aExtraData The ExtraData string which can have a format of + * either 'controller=13;channel=3' or '11'. + * @param pszKey The string being looked up, usually either 'controller' + * or 'channel' but can be NULL or empty. + * @param puVal The integer value of the 'controller=' or 'channel=' + * key (or the controller number when there is no key) in + * the ExtraData string. + * @returns COM status code. + */ +static int getStorageControllerDetailsFromStr(const com::Utf8Str &aExtraData, const char *pszKey, uint32_t *puVal) +{ + int vrc; + + if (pszKey && *pszKey) + { + size_t posKey = aExtraData.find(pszKey); + if (posKey == Utf8Str::npos) + return VERR_INVALID_PARAMETER; + vrc = RTStrToUInt32Ex(aExtraData.c_str() + posKey + strlen(pszKey), NULL, 0, puVal); + } + else + { + vrc = RTStrToUInt32Ex(aExtraData.c_str(), NULL, 0, puVal); + } + + if (vrc == VWRN_NUMBER_TOO_BIG || vrc == VWRN_NEGATIVE_UNSIGNED) + return VERR_INVALID_PARAMETER; + + return vrc; +} + +static bool isStorageControllerType(VirtualSystemDescriptionType_T avsdType) +{ + switch (avsdType) + { + case VirtualSystemDescriptionType_HardDiskControllerIDE: + case VirtualSystemDescriptionType_HardDiskControllerSATA: + case VirtualSystemDescriptionType_HardDiskControllerSCSI: + case VirtualSystemDescriptionType_HardDiskControllerSAS: + case VirtualSystemDescriptionType_HardDiskControllerVirtioSCSI: + return true; + default: + return false; + } +} + +static const RTGETOPTDEF g_aImportApplianceOptions[] = +{ + { "--dry-run", 'n', RTGETOPT_REQ_NOTHING }, + { "-dry-run", 'n', RTGETOPT_REQ_NOTHING }, // deprecated + { "--dryrun", 'n', RTGETOPT_REQ_NOTHING }, + { "-dryrun", 'n', RTGETOPT_REQ_NOTHING }, // deprecated + { "--detailed-progress", 'P', RTGETOPT_REQ_NOTHING }, + { "-detailed-progress", 'P', RTGETOPT_REQ_NOTHING }, // deprecated + { "--vsys", 's', RTGETOPT_REQ_UINT32 }, + { "-vsys", 's', RTGETOPT_REQ_UINT32 }, // deprecated + { "--ostype", 'o', RTGETOPT_REQ_STRING }, + { "-ostype", 'o', RTGETOPT_REQ_STRING }, // deprecated + { "--vmname", 'V', RTGETOPT_REQ_STRING }, + { "-vmname", 'V', RTGETOPT_REQ_STRING }, // deprecated + { "--settingsfile", 'S', RTGETOPT_REQ_STRING }, + { "--basefolder", 'p', RTGETOPT_REQ_STRING }, + { "--group", 'g', RTGETOPT_REQ_STRING }, + { "--memory", 'm', RTGETOPT_REQ_STRING }, + { "-memory", 'm', RTGETOPT_REQ_STRING }, // deprecated + { "--cpus", 'c', RTGETOPT_REQ_STRING }, + { "--description", 'd', RTGETOPT_REQ_STRING }, + { "--eula", 'L', RTGETOPT_REQ_STRING }, + { "-eula", 'L', RTGETOPT_REQ_STRING }, // deprecated + { "--unit", 'u', RTGETOPT_REQ_UINT32 }, + { "-unit", 'u', RTGETOPT_REQ_UINT32 }, // deprecated + { "--ignore", 'x', RTGETOPT_REQ_NOTHING }, + { "-ignore", 'x', RTGETOPT_REQ_NOTHING }, // deprecated + { "--scsitype", 'T', RTGETOPT_REQ_UINT32 }, + { "-scsitype", 'T', RTGETOPT_REQ_UINT32 }, // deprecated + { "--type", 'T', RTGETOPT_REQ_UINT32 }, // deprecated + { "-type", 'T', RTGETOPT_REQ_UINT32 }, // deprecated + { "--controller", 'C', RTGETOPT_REQ_STRING }, + { "--port", 'E', RTGETOPT_REQ_STRING }, + { "--disk", 'D', RTGETOPT_REQ_STRING }, + { "--options", 'O', RTGETOPT_REQ_STRING }, + + { "--cloud", 'j', RTGETOPT_REQ_NOTHING}, + { "--cloudprofile", 'k', RTGETOPT_REQ_STRING }, + { "--cloudinstanceid", 'l', RTGETOPT_REQ_STRING }, + { "--cloudbucket", 'B', RTGETOPT_REQ_STRING } +}; + +typedef enum APPLIANCETYPE +{ + NOT_SET, LOCAL, CLOUD +} APPLIANCETYPE; + +RTEXITCODE handleImportAppliance(HandlerArg *arg) +{ + HRESULT hrc = S_OK; + APPLIANCETYPE enmApplType = NOT_SET; + Utf8Str strOvfFilename; + bool fExecute = true; // if true, then we actually do the import + com::SafeArray<ImportOptions_T> options; + uint32_t ulCurVsys = (uint32_t)-1; + uint32_t ulCurUnit = (uint32_t)-1; + // for each --vsys X command, maintain a map of command line items + // (we'll parse them later after interpreting the OVF, when we can + // actually check whether they make sense semantically) + ArgsMapsMap mapArgsMapsPerVsys; + IgnoresMapsMap mapIgnoresMapsPerVsys; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, arg->argc, arg->argv, g_aImportApplianceOptions, RT_ELEMENTS(g_aImportApplianceOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'n': // --dry-run + fExecute = false; + break; + + case 'P': // --detailed-progress + g_fDetailedProgress = true; + break; + + case 's': // --vsys + if (enmApplType == NOT_SET) + enmApplType = LOCAL; + + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" can't be used together with \"--cloud\" option."), + GetState.pDef->pszLong); + if (ValueUnion.u32 == (uint32_t)-1) + return errorSyntax(Appliance::tr("Value of option \"%s\" is out of range."), + GetState.pDef->pszLong); + + ulCurVsys = ValueUnion.u32; + ulCurUnit = (uint32_t)-1; + break; + + case 'o': // --ostype + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["ostype"] = ValueUnion.psz; + break; + + case 'V': // --vmname + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["vmname"] = ValueUnion.psz; + break; + + case 'S': // --settingsfile + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["settingsfile"] = ValueUnion.psz; + break; + + case 'p': // --basefolder + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["basefolder"] = ValueUnion.psz; + break; + + case 'g': // --group + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["group"] = ValueUnion.psz; + break; + + case 'd': // --description + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz; + break; + + case 'L': // --eula + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz; + break; + + case 'm': // --memory + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["memory"] = ValueUnion.psz; + break; + + case 'c': // --cpus + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cpus"] = ValueUnion.psz; + break; + + case 'u': // --unit + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + if (ValueUnion.u32 == (uint32_t)-1) + return errorSyntax(Appliance::tr("Value of option \"%s\" is out of range."), + GetState.pDef->pszLong); + + ulCurUnit = ValueUnion.u32; + break; + + case 'x': // --ignore + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + if (ulCurUnit == (uint32_t)-1) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --unit option."), + GetState.pDef->pszLong); + mapIgnoresMapsPerVsys[ulCurVsys][ulCurUnit] = true; + break; + + case 'T': // --scsitype + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + if (ulCurUnit == (uint32_t)-1) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --unit option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys][Utf8StrFmt("scsitype%u", ulCurUnit)] = ValueUnion.psz; + break; + + case 'C': // --controller + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + if (ulCurUnit == (uint32_t)-1) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --unit option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys][Utf8StrFmt("controller%u", ulCurUnit)] = ValueUnion.psz; + break; + + case 'E': // --port + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + if (ulCurUnit == (uint32_t)-1) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --unit option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys][Utf8StrFmt("port%u", ulCurUnit)] = ValueUnion.psz; + break; + + case 'D': // --disk + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + if (ulCurUnit == (uint32_t)-1) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --unit option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys][Utf8StrFmt("disk%u", ulCurUnit)] = ValueUnion.psz; + break; + + case 'O': // --options + if (RT_FAILURE(parseImportOptions(ValueUnion.psz, &options))) + return errorArgument(Appliance::tr("Invalid import options '%s'\n"), ValueUnion.psz); + break; + + /*--cloud and --vsys are orthogonal, only one must be presented*/ + case 'j': // --cloud + if (enmApplType == NOT_SET) + enmApplType = CLOUD; + + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" can't be used together with \"--vsys\" option."), + GetState.pDef->pszLong); + + ulCurVsys = 0; + break; + + /* Cloud export settings */ + case 'k': // --cloudprofile + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudprofile"] = ValueUnion.psz; + break; + + case 'l': // --cloudinstanceid + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudinstanceid"] = ValueUnion.psz; + break; + + case 'B': // --cloudbucket + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudbucket"] = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + if (strOvfFilename.isEmpty()) + strOvfFilename = ValueUnion.psz; + else + return errorSyntax(Appliance::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Appliance::tr("Invalid option -%c"), c); + else + return errorSyntax(Appliance::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Appliance::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Appliance::tr("error: %Rrs"), c); + } + } + + /* Last check after parsing all arguments */ + if (strOvfFilename.isEmpty()) + return errorSyntax(Appliance::tr("Not enough arguments for \"import\" command.")); + + if (enmApplType == NOT_SET) + enmApplType = LOCAL; + + do + { + ComPtr<IAppliance> pAppliance; + CHECK_ERROR_BREAK(arg->virtualBox, CreateAppliance(pAppliance.asOutParam())); + //in the case of Cloud, append the instance id here because later it's harder to do + if (enmApplType == CLOUD) + { + try + { + /* Check presence of cloudprofile and cloudinstanceid in the map. + * If there isn't the exception is triggered. It's standard std:map logic.*/ + ArgsMap a = mapArgsMapsPerVsys[ulCurVsys]; + (void)a.at("cloudprofile"); + (void)a.at("cloudinstanceid"); + } + catch (...) + { + return errorSyntax(Appliance::tr("Not enough arguments for import from the Cloud.")); + } + + strOvfFilename.append(mapArgsMapsPerVsys[ulCurVsys]["cloudprofile"]); + strOvfFilename.append("/"); + strOvfFilename.append(mapArgsMapsPerVsys[ulCurVsys]["cloudinstanceid"]); + } + + char *pszAbsFilePath; + if (strOvfFilename.startsWith("S3://", RTCString::CaseInsensitive) || + strOvfFilename.startsWith("SunCloud://", RTCString::CaseInsensitive) || + strOvfFilename.startsWith("webdav://", RTCString::CaseInsensitive) || + strOvfFilename.startsWith("OCI://", RTCString::CaseInsensitive)) + pszAbsFilePath = RTStrDup(strOvfFilename.c_str()); + else + pszAbsFilePath = RTPathAbsDup(strOvfFilename.c_str()); + + ComPtr<IProgress> progressRead; + CHECK_ERROR_BREAK(pAppliance, Read(Bstr(pszAbsFilePath).raw(), + progressRead.asOutParam())); + RTStrFree(pszAbsFilePath); + + hrc = showProgress(progressRead); + CHECK_PROGRESS_ERROR_RET(progressRead, (Appliance::tr("Appliance read failed")), RTEXITCODE_FAILURE); + + Bstr path; /* fetch the path, there is stuff like username/password removed if any */ + CHECK_ERROR_BREAK(pAppliance, COMGETTER(Path)(path.asOutParam())); + + size_t cVirtualSystemDescriptions = 0; + com::SafeIfaceArray<IVirtualSystemDescription> aVirtualSystemDescriptions; + + if (enmApplType == LOCAL) + { + // call interpret(); this can yield both warnings and errors, so we need + // to tinker with the error info a bit + RTStrmPrintf(g_pStdErr, Appliance::tr("Interpreting %ls...\n"), path.raw()); + hrc = pAppliance->Interpret(); + com::ErrorInfoKeeper eik; + + /** @todo r=klaus Eliminate this special way of signalling + * warnings which should be part of the ErrorInfo. */ + com::SafeArray<BSTR> aWarnings; + if (SUCCEEDED(pAppliance->GetWarnings(ComSafeArrayAsOutParam(aWarnings)))) + { + size_t cWarnings = aWarnings.size(); + for (unsigned i = 0; i < cWarnings; ++i) + { + Bstr bstrWarning(aWarnings[i]); + RTMsgWarning("%ls", bstrWarning.raw()); + } + } + + eik.restore(); + if (FAILED(hrc)) // during interpret, after printing warnings + { + com::GlueHandleComError(pAppliance, "Interpret()", hrc, __FILE__, __LINE__); + break; + } + + RTStrmPrintf(g_pStdErr, "OK.\n"); + + // fetch all disks + com::SafeArray<BSTR> retDisks; + CHECK_ERROR_BREAK(pAppliance, + COMGETTER(Disks)(ComSafeArrayAsOutParam(retDisks))); + if (retDisks.size() > 0) + { + RTPrintf(Appliance::tr("Disks:\n")); + for (unsigned i = 0; i < retDisks.size(); i++) + RTPrintf(" %ls\n", retDisks[i]); + RTPrintf("\n"); + } + + // fetch virtual system descriptions + CHECK_ERROR_BREAK(pAppliance, + COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(aVirtualSystemDescriptions))); + + cVirtualSystemDescriptions = aVirtualSystemDescriptions.size(); + + // match command line arguments with virtual system descriptions; + // this is only to sort out invalid indices at this time + ArgsMapsMap::const_iterator it; + for (it = mapArgsMapsPerVsys.begin(); + it != mapArgsMapsPerVsys.end(); + ++it) + { + uint32_t ulVsys = it->first; + if (ulVsys >= cVirtualSystemDescriptions) + return errorSyntax(Appliance::tr("Invalid index %RI32 with -vsys option; the OVF contains only %zu virtual system(s).", + "", cVirtualSystemDescriptions), + ulVsys, cVirtualSystemDescriptions); + } + } + else if (enmApplType == CLOUD) + { + /* In the Cloud case the call of interpret() isn't needed because there isn't any OVF XML file. + * All info is got from the Cloud and VSD is filled inside IAppliance::read(). */ + // fetch virtual system descriptions + CHECK_ERROR_BREAK(pAppliance, + COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(aVirtualSystemDescriptions))); + + cVirtualSystemDescriptions = aVirtualSystemDescriptions.size(); + } + + uint32_t cLicensesInTheWay = 0; + + // dump virtual system descriptions and match command-line arguments + if (cVirtualSystemDescriptions > 0) + { + for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i) + { + com::SafeArray<VirtualSystemDescriptionType_T> retTypes; + com::SafeArray<BSTR> aRefs; + com::SafeArray<BSTR> aOvfValues; + com::SafeArray<BSTR> aVBoxValues; + com::SafeArray<BSTR> aExtraConfigValues; + CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i], + GetDescription(ComSafeArrayAsOutParam(retTypes), + ComSafeArrayAsOutParam(aRefs), + ComSafeArrayAsOutParam(aOvfValues), + ComSafeArrayAsOutParam(aVBoxValues), + ComSafeArrayAsOutParam(aExtraConfigValues))); + + RTPrintf(Appliance::tr("Virtual system %u:\n"), i); + + // look up the corresponding command line options, if any + ArgsMap *pmapArgs = NULL; + ArgsMapsMap::iterator itm = mapArgsMapsPerVsys.find(i); + if (itm != mapArgsMapsPerVsys.end()) + pmapArgs = &itm->second; + + // this collects the final values for setFinalValues() + com::SafeArray<BOOL> aEnabled(retTypes.size()); + com::SafeArray<BSTR> aFinalValues(retTypes.size()); + + for (unsigned a = 0; a < retTypes.size(); ++a) + { + VirtualSystemDescriptionType_T t = retTypes[a]; + + Utf8Str strOverride; + + Bstr bstrFinalValue = aVBoxValues[a]; + + bool fIgnoreThis = mapIgnoresMapsPerVsys[i][a]; + + aEnabled[a] = true; + + switch (t) + { + case VirtualSystemDescriptionType_OS: + if (findArgValue(strOverride, pmapArgs, "ostype")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: OS type specified with --ostype: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested OS type: \"%ls\"\n" + " (change with \"--vsys %u --ostype <type>\"; use \"list ostypes\" to list all possible values)\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_Name: + if (findArgValue(strOverride, pmapArgs, "vmname")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: VM name specified with --vmname: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested VM name \"%ls\"\n" + " (change with \"--vsys %u --vmname <name>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_Product: + RTPrintf(Appliance::tr("%2u: Product (ignored): %ls\n"), + a, aVBoxValues[a]); + break; + + case VirtualSystemDescriptionType_ProductUrl: + RTPrintf(Appliance::tr("%2u: ProductUrl (ignored): %ls\n"), + a, aVBoxValues[a]); + break; + + case VirtualSystemDescriptionType_Vendor: + RTPrintf(Appliance::tr("%2u: Vendor (ignored): %ls\n"), + a, aVBoxValues[a]); + break; + + case VirtualSystemDescriptionType_VendorUrl: + RTPrintf(Appliance::tr("%2u: VendorUrl (ignored): %ls\n"), + a, aVBoxValues[a]); + break; + + case VirtualSystemDescriptionType_Version: + RTPrintf(Appliance::tr("%2u: Version (ignored): %ls\n"), + a, aVBoxValues[a]); + break; + + case VirtualSystemDescriptionType_Description: + if (findArgValue(strOverride, pmapArgs, "description")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: Description specified with --description: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Description \"%ls\"\n" + " (change with \"--vsys %u --description <desc>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_License: + ++cLicensesInTheWay; + if (findArgValue(strOverride, pmapArgs, "eula")) + { + if (strOverride == "show") + { + RTPrintf(Appliance::tr("%2u: End-user license agreement\n" + " (accept with \"--vsys %u --eula accept\"):\n" + "\n%ls\n\n"), + a, i, bstrFinalValue.raw()); + } + else if (strOverride == "accept") + { + RTPrintf(Appliance::tr("%2u: End-user license agreement (accepted)\n"), + a); + --cLicensesInTheWay; + } + else + return errorSyntax(Appliance::tr("Argument to --eula must be either \"show\" or \"accept\".")); + } + else + RTPrintf(Appliance::tr("%2u: End-user license agreement\n" + " (display with \"--vsys %u --eula show\";\n" + " accept with \"--vsys %u --eula accept\")\n"), + a, i, i); + break; + + case VirtualSystemDescriptionType_CPU: + if (findArgValue(strOverride, pmapArgs, "cpus")) + { + uint32_t cCPUs; + if ( strOverride.toInt(cCPUs) == VINF_SUCCESS + && cCPUs >= VMM_MIN_CPU_COUNT + && cCPUs <= VMM_MAX_CPU_COUNT + ) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: No. of CPUs specified with --cpus: %ls\n"), + a, bstrFinalValue.raw()); + } + else + return errorSyntax(Appliance::tr("Argument to --cpus option must be a number greater than %d and less than %d."), + VMM_MIN_CPU_COUNT - 1, VMM_MAX_CPU_COUNT + 1); + } + else + RTPrintf(Appliance::tr("%2u: Number of CPUs: %ls\n (change with \"--vsys %u --cpus <n>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_Memory: + { + if (findArgValue(strOverride, pmapArgs, "memory")) + { + uint32_t ulMemMB; + if (VINF_SUCCESS == strOverride.toInt(ulMemMB)) + { + /* 'VBoxManage import --memory' size is in megabytes */ + RTPrintf(Appliance::tr("%2u: Guest memory specified with --memory: %RU32 MB\n"), + a, ulMemMB); + + /* IVirtualSystemDescription guest memory size is in bytes. + It's always stored in bytes in VSD according to the old internal agreement within the team */ + uint64_t ullMemBytes = (uint64_t)ulMemMB * _1M; + strOverride = Utf8StrFmt("%RU64", ullMemBytes); + bstrFinalValue = strOverride; + } + else + return errorSyntax(Appliance::tr("Argument to --memory option must be a non-negative number.")); + } + else + { + strOverride = aVBoxValues[a]; + uint64_t ullMemMB = strOverride.toUInt64() / _1M; + RTPrintf(Appliance::tr("%2u: Guest memory: %RU64 MB\n (change with \"--vsys %u --memory <MB>\")\n"), + a, ullMemMB, i); + } + break; + } + + case VirtualSystemDescriptionType_HardDiskControllerIDE: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: IDE controller, type %ls -- disabled\n"), + a, + aVBoxValues[a]); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: IDE controller, type %ls\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aVBoxValues[a], + i, a); + break; + + case VirtualSystemDescriptionType_HardDiskControllerSATA: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: SATA controller, type %ls -- disabled\n"), + a, + aVBoxValues[a]); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: SATA controller, type %ls\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aVBoxValues[a], + i, a); + break; + + case VirtualSystemDescriptionType_HardDiskControllerSAS: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: SAS controller, type %ls -- disabled\n"), + a, + aVBoxValues[a]); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: SAS controller, type %ls\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aVBoxValues[a], + i, a); + break; + + case VirtualSystemDescriptionType_HardDiskControllerSCSI: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: SCSI controller, type %ls -- disabled\n"), + a, + aVBoxValues[a]); + aEnabled[a] = false; + } + else + { + Utf8StrFmt strTypeArg("scsitype%u", a); + if (findArgValue(strOverride, pmapArgs, strTypeArg)) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: SCSI controller, type set with --unit %u --scsitype: \"%ls\"\n"), + a, + a, + bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: SCSI controller, type %ls\n" + " (change with \"--vsys %u --unit %u --scsitype {BusLogic|LsiLogic}\";\n" + " disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aVBoxValues[a], + i, a, i, a); + } + break; + + case VirtualSystemDescriptionType_HardDiskControllerVirtioSCSI: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: VirtioSCSI controller, type %ls -- disabled\n"), + a, + aVBoxValues[a]); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: VirtioSCSI controller, type %ls\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aVBoxValues[a], + i, a); + break; + + case VirtualSystemDescriptionType_HardDiskControllerNVMe: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: NVMe controller, type %ls -- disabled\n"), + a, + aVBoxValues[a]); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: NVMe controller, type %ls\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aVBoxValues[a], + i, a); + break; + + case VirtualSystemDescriptionType_HardDiskImage: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: Hard disk image: source image=%ls -- disabled\n"), + a, + aOvfValues[a]); + aEnabled[a] = false; + } + else + { + Utf8StrFmt strTypeArg("disk%u", a); + bool fDiskChanged = false; + int vrc; + RTCList<ImportOptions_T> optionsList = options.toList(); + + if (findArgValue(strOverride, pmapArgs, strTypeArg)) + { + if (optionsList.contains(ImportOptions_ImportToVDI)) + return errorSyntax(Appliance::tr("Option --ImportToVDI can not be used together with a manually set target path.")); + RTUUID uuid; + /* Check if this is a uuid. If so, don't touch. */ + vrc = RTUuidFromStr(&uuid, strOverride.c_str()); + if (vrc != VINF_SUCCESS) + { + /* Make the path absolute. */ + if (!RTPathStartsWithRoot(strOverride.c_str())) + { + char pszPwd[RTPATH_MAX]; + vrc = RTPathGetCurrent(pszPwd, RTPATH_MAX); + if (RT_SUCCESS(vrc)) + strOverride = Utf8Str(pszPwd).append(RTPATH_SLASH).append(strOverride); + } + } + bstrFinalValue = strOverride; + fDiskChanged = true; + } + + strTypeArg.printf("controller%u", a); + bool fControllerChanged = false; + uint32_t uTargetController = (uint32_t)-1; + VirtualSystemDescriptionType_T vsdControllerType = VirtualSystemDescriptionType_Ignore; + Utf8Str strExtraConfigValue; + if (findArgValue(strOverride, pmapArgs, strTypeArg)) + { + vrc = getStorageControllerDetailsFromStr(strOverride, NULL, &uTargetController); + if (RT_FAILURE(vrc)) + return errorSyntax(Appliance::tr("Invalid controller value: '%s'"), + strOverride.c_str()); + + vsdControllerType = retTypes[uTargetController]; + if (!isStorageControllerType(vsdControllerType)) + return errorSyntax(Appliance::tr("Invalid storage controller specified: %u"), + uTargetController); + + fControllerChanged = true; + } + + strTypeArg.printf("port%u", a); + bool fControllerPortChanged = false; + uint32_t uTargetControllerPort = (uint32_t)-1;; + if (findArgValue(strOverride, pmapArgs, strTypeArg)) + { + vrc = getStorageControllerDetailsFromStr(strOverride, NULL, &uTargetControllerPort); + if (RT_FAILURE(vrc)) + return errorSyntax(Appliance::tr("Invalid port value: '%s'"), + strOverride.c_str()); + + fControllerPortChanged = true; + } + + /* + * aExtraConfigValues[a] has a format of 'controller=12;channel=0' and is set by + * Appliance::interpret() so any parsing errors here aren't due to user-supplied + * values so different error messages here. + */ + uint32_t uOrigController; + Utf8Str strOrigController(Bstr(aExtraConfigValues[a]).raw()); + vrc = getStorageControllerDetailsFromStr(strOrigController, "controller=", &uOrigController); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Appliance::tr("Failed to extract controller value from ExtraConfig: '%s'"), + strOrigController.c_str()); + + uint32_t uOrigControllerPort; + vrc = getStorageControllerDetailsFromStr(strOrigController, "channel=", &uOrigControllerPort); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Appliance::tr("Failed to extract channel value from ExtraConfig: '%s'"), + strOrigController.c_str()); + + /* + * The 'strExtraConfigValue' string is used to display the storage controller and + * port details for each virtual hard disk using the more accurate 'controller=' and + * 'port=' labels. The aExtraConfigValues[a] string has a format of + * 'controller=%u;channel=%u' from Appliance::interpret() which is required as per + * the API but for consistency and clarity with the CLI options --controller and + * --port we instead use strExtraConfigValue in the output below. + */ + strExtraConfigValue = Utf8StrFmt("controller=%u;port=%u", uOrigController, uOrigControllerPort); + + if (fControllerChanged || fControllerPortChanged) + { + /* + * Verify that the new combination of controller and controller port is valid. + * cf. StorageController::i_checkPortAndDeviceValid() + */ + if (uTargetControllerPort == (uint32_t)-1) + uTargetControllerPort = uOrigControllerPort; + if (uTargetController == (uint32_t)-1) + uTargetController = uOrigController; + + if ( uOrigController == uTargetController + && uOrigControllerPort == uTargetControllerPort) + return errorSyntax(Appliance::tr("Device already attached to controller %u at this port (%u) location."), + uTargetController, + uTargetControllerPort); + + if (vsdControllerType == VirtualSystemDescriptionType_Ignore) + vsdControllerType = retTypes[uOrigController]; + if (!isStorageControllerType(vsdControllerType)) + return errorSyntax(Appliance::tr("Invalid storage controller specified: %u"), + uOrigController); + + ComPtr<IVirtualBox> pVirtualBox = arg->virtualBox; + ComPtr<ISystemProperties> systemProperties; + CHECK_ERROR(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam())); + ULONG maxPorts = 0; + StorageBus_T enmStorageBus = StorageBus_Null;; + switch (vsdControllerType) + { + case VirtualSystemDescriptionType_HardDiskControllerIDE: + enmStorageBus = StorageBus_IDE; + break; + case VirtualSystemDescriptionType_HardDiskControllerSATA: + enmStorageBus = StorageBus_SATA; + break; + case VirtualSystemDescriptionType_HardDiskControllerSCSI: + enmStorageBus = StorageBus_SCSI; + break; + case VirtualSystemDescriptionType_HardDiskControllerSAS: + enmStorageBus = StorageBus_SAS; + break; + case VirtualSystemDescriptionType_HardDiskControllerVirtioSCSI: + enmStorageBus = StorageBus_VirtioSCSI; + break; + default: // Not reached since vsdControllerType validated above but silence gcc. + break; + } + CHECK_ERROR_RET(systemProperties, GetMaxPortCountForStorageBus(enmStorageBus, &maxPorts), + RTEXITCODE_FAILURE); + if (uTargetControllerPort >= maxPorts) + return errorSyntax(Appliance::tr("Illegal port value: %u. For %ls controllers the only valid values are 0 to %lu (inclusive)"), + uTargetControllerPort, + aVBoxValues[uTargetController], + maxPorts); + + /* + * The 'strOverride' string will be mapped to the strExtraConfigCurrent value in + * VirtualSystemDescription::setFinalValues() which is then used in the appliance + * import routines i_importVBoxMachine()/i_importMachineGeneric() later. This + * aExtraConfigValues[] array entry must have a format of + * 'controller=<index>;channel=<c>' as per the API documentation. + */ + strExtraConfigValue = Utf8StrFmt("controller=%u;port=%u", uTargetController, + uTargetControllerPort); + strOverride = Utf8StrFmt("controller=%u;channel=%u", uTargetController, + uTargetControllerPort); + Bstr bstrExtraConfigValue = strOverride; + bstrExtraConfigValue.detachTo(&aExtraConfigValues[a]); + } + + if (fDiskChanged && !fControllerChanged && !fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --disk: source image=%ls, target path=%ls, %s\n" + " (change controller with \"--vsys %u --unit %u --controller <index>\";\n" + " change controller port with \"--vsys %u --unit %u --port <n>\")\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str(), + i, a, + i, a); + } + else if (fDiskChanged && fControllerChanged && !fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --disk and --controller: source image=%ls, target path=%ls, %s\n" + " (change controller port with \"--vsys %u --unit %u --port <n>\")\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str(), + i, a); + } + else if (fDiskChanged && !fControllerChanged && fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --disk and --port: source image=%ls, target path=%ls, %s\n" + " (change controller with \"--vsys %u --unit %u --controller <index>\")\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str(), + i, a); + } + else if (!fDiskChanged && fControllerChanged && fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --controller and --port: source image=%ls, target path=%ls, %s\n" + " (change target path with \"--vsys %u --unit %u --disk path\")\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str(), + i, a); + } + else if (!fDiskChanged && !fControllerChanged && fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --port: source image=%ls, target path=%ls, %s\n" + " (change target path with \"--vsys %u --unit %u --disk path\";\n" + " change controller with \"--vsys %u --unit %u --controller <index>\")\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str(), + i, a, + i, a); + } + else if (!fDiskChanged && fControllerChanged && !fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --controller: source image=%ls, target path=%ls, %s\n" + " (change target path with \"--vsys %u --unit %u --disk path\";\n" + " change controller port with \"--vsys %u --unit %u --port <n>\")\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str(), + i, a, + i, a); + } + else if (fDiskChanged && fControllerChanged && fControllerPortChanged) + { + RTPrintf(Appliance::tr("%2u: Hard disk image specified with --disk and --controller and --port: source image=%ls, target path=%ls, %s\n"), + a, + aOvfValues[a], + bstrFinalValue.raw(), + strExtraConfigValue.c_str()); + } + else + { + strOverride = aVBoxValues[a]; + + /* + * Current solution isn't optimal. + * Better way is to provide API call for function + * Appliance::i_findMediumFormatFromDiskImage() + * and creating one new function which returns + * struct ovf::DiskImage for currently processed disk. + */ + + /* + * if user wants to convert all imported disks to VDI format + * we need to replace files extensions to "vdi" + * except CD/DVD disks + */ + if (optionsList.contains(ImportOptions_ImportToVDI)) + { + ComPtr<IVirtualBox> pVirtualBox = arg->virtualBox; + ComPtr<ISystemProperties> systemProperties; + com::SafeIfaceArray<IMediumFormat> mediumFormats; + Bstr bstrFormatName; + + CHECK_ERROR(pVirtualBox, + COMGETTER(SystemProperties)(systemProperties.asOutParam())); + + CHECK_ERROR(systemProperties, + COMGETTER(MediumFormats)(ComSafeArrayAsOutParam(mediumFormats))); + + /* go through all supported media formats and store files extensions only for RAW */ + com::SafeArray<BSTR> extensions; + + for (unsigned j = 0; j < mediumFormats.size(); ++j) + { + com::SafeArray<DeviceType_T> deviceType; + ComPtr<IMediumFormat> mediumFormat = mediumFormats[j]; + CHECK_ERROR(mediumFormat, COMGETTER(Name)(bstrFormatName.asOutParam())); + Utf8Str strFormatName = Utf8Str(bstrFormatName); + + if (strFormatName.compare("RAW", Utf8Str::CaseInsensitive) == 0) + { + /* getting files extensions for "RAW" format */ + CHECK_ERROR(mediumFormat, + DescribeFileExtensions(ComSafeArrayAsOutParam(extensions), + ComSafeArrayAsOutParam(deviceType))); + break; + } + } + + /* go through files extensions for RAW format and compare them with + * extension of current file + */ + bool fReplace = true; + + const char *pszExtension = RTPathSuffix(strOverride.c_str()); + if (pszExtension) + pszExtension++; + + for (unsigned j = 0; j < extensions.size(); ++j) + { + Bstr bstrExt(extensions[j]); + Utf8Str strExtension(bstrExt); + if(strExtension.compare(pszExtension, Utf8Str::CaseInsensitive) == 0) + { + fReplace = false; + break; + } + } + + if (fReplace) + { + strOverride = strOverride.stripSuffix(); + strOverride = strOverride.append(".").append("vdi"); + } + } + + bstrFinalValue = strOverride; + + RTPrintf(Appliance::tr("%2u: Hard disk image: source image=%ls, target path=%ls, %s\n" + " (change target path with \"--vsys %u --unit %u --disk path\";\n" + " change controller with \"--vsys %u --unit %u --controller <index>\";\n" + " change controller port with \"--vsys %u --unit %u --port <n>\";\n" + " disable with \"--vsys %u --unit %u --ignore\")\n"), + a, aOvfValues[a], bstrFinalValue.raw(), strExtraConfigValue.c_str(), + i, a, + i, a, + i, a, + i, a); + } + } + break; + + case VirtualSystemDescriptionType_CDROM: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: CD-ROM -- disabled\n"), + a); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: CD-ROM\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, i, a); + break; + + case VirtualSystemDescriptionType_Floppy: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: Floppy -- disabled\n"), + a); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: Floppy\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, i, a); + break; + + case VirtualSystemDescriptionType_NetworkAdapter: + RTPrintf(Appliance::tr("%2u: Network adapter: orig %ls, config %ls, extra %ls\n"), /// @todo implement once we have a plan for the back-end + a, + aOvfValues[a], + aVBoxValues[a], + aExtraConfigValues[a]); + break; + + case VirtualSystemDescriptionType_USBController: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: USB controller -- disabled\n"), + a); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: USB controller\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, i, a); + break; + + case VirtualSystemDescriptionType_SoundCard: + if (fIgnoreThis) + { + RTPrintf(Appliance::tr("%2u: Sound card \"%ls\" -- disabled\n"), + a, + aOvfValues[a]); + aEnabled[a] = false; + } + else + RTPrintf(Appliance::tr("%2u: Sound card (appliance expects \"%ls\", can change on import)\n" + " (disable with \"--vsys %u --unit %u --ignore\")\n"), + a, + aOvfValues[a], + i, + a); + break; + + case VirtualSystemDescriptionType_SettingsFile: + if (findArgValue(strOverride, pmapArgs, "settingsfile")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: VM settings file name specified with --settingsfile: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested VM settings file name \"%ls\"\n" + " (change with \"--vsys %u --settingsfile <filename>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_BaseFolder: + if (findArgValue(strOverride, pmapArgs, "basefolder")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: VM base folder specified with --basefolder: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested VM base folder \"%ls\"\n" + " (change with \"--vsys %u --basefolder <path>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_PrimaryGroup: + if (findArgValue(strOverride, pmapArgs, "group")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: VM group specified with --group: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested VM group \"%ls\"\n" + " (change with \"--vsys %u --group <group>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_CloudInstanceShape: + RTPrintf(Appliance::tr("%2u: Suggested cloud shape \"%ls\"\n"), + a, bstrFinalValue.raw()); + break; + + case VirtualSystemDescriptionType_CloudBucket: + if (findArgValue(strOverride, pmapArgs, "cloudbucket")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: Cloud bucket id specified with --cloudbucket: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested cloud bucket id \"%ls\"\n" + " (change with \"--cloud %u --cloudbucket <id>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_CloudProfileName: + if (findArgValue(strOverride, pmapArgs, "cloudprofile")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: Cloud profile name specified with --cloudprofile: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested cloud profile name \"%ls\"\n" + " (change with \"--cloud %u --cloudprofile <id>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_CloudInstanceId: + if (findArgValue(strOverride, pmapArgs, "cloudinstanceid")) + { + bstrFinalValue = strOverride; + RTPrintf(Appliance::tr("%2u: Cloud instance id specified with --cloudinstanceid: \"%ls\"\n"), + a, bstrFinalValue.raw()); + } + else + RTPrintf(Appliance::tr("%2u: Suggested cloud instance id \"%ls\"\n" + " (change with \"--cloud %u --cloudinstanceid <id>\")\n"), + a, bstrFinalValue.raw(), i); + break; + + case VirtualSystemDescriptionType_CloudImageId: + RTPrintf(Appliance::tr("%2u: Suggested cloud base image id \"%ls\"\n"), + a, bstrFinalValue.raw()); + break; + case VirtualSystemDescriptionType_CloudDomain: + case VirtualSystemDescriptionType_CloudBootDiskSize: + case VirtualSystemDescriptionType_CloudOCIVCN: + case VirtualSystemDescriptionType_CloudPublicIP: + case VirtualSystemDescriptionType_CloudOCISubnet: + case VirtualSystemDescriptionType_CloudKeepObject: + case VirtualSystemDescriptionType_CloudLaunchInstance: + case VirtualSystemDescriptionType_CloudInstanceState: + case VirtualSystemDescriptionType_CloudImageState: + case VirtualSystemDescriptionType_Miscellaneous: + case VirtualSystemDescriptionType_CloudInstanceDisplayName: + case VirtualSystemDescriptionType_CloudImageDisplayName: + case VirtualSystemDescriptionType_CloudOCILaunchMode: + case VirtualSystemDescriptionType_CloudPrivateIP: + case VirtualSystemDescriptionType_CloudBootVolumeId: + case VirtualSystemDescriptionType_CloudOCIVCNCompartment: + case VirtualSystemDescriptionType_CloudOCISubnetCompartment: + case VirtualSystemDescriptionType_CloudPublicSSHKey: + case VirtualSystemDescriptionType_BootingFirmware: + case VirtualSystemDescriptionType_CloudInitScriptPath: + case VirtualSystemDescriptionType_CloudCompartmentId: + case VirtualSystemDescriptionType_CloudShapeCpus: + case VirtualSystemDescriptionType_CloudShapeMemory: + case VirtualSystemDescriptionType_CloudInstanceMetadata: + case VirtualSystemDescriptionType_CloudInstanceFreeFormTags: + case VirtualSystemDescriptionType_CloudImageFreeFormTags: + /** @todo VirtualSystemDescriptionType_Miscellaneous? */ + break; + + case VirtualSystemDescriptionType_Ignore: +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case VirtualSystemDescriptionType_32BitHack: +#endif + break; + } + + bstrFinalValue.detachTo(&aFinalValues[a]); + } + + if (fExecute) + CHECK_ERROR_BREAK(aVirtualSystemDescriptions[i], + SetFinalValues(ComSafeArrayAsInParam(aEnabled), + ComSafeArrayAsInParam(aFinalValues), + ComSafeArrayAsInParam(aExtraConfigValues))); + + } // for (unsigned i = 0; i < cVirtualSystemDescriptions; ++i) + + if (cLicensesInTheWay == 1) + RTMsgError(Appliance::tr("Cannot import until the license agreement listed above is accepted.")); + else if (cLicensesInTheWay > 1) + RTMsgError(Appliance::tr("Cannot import until the %c license agreements listed above are accepted."), + cLicensesInTheWay); + + if (!cLicensesInTheWay && fExecute) + { + // go! + ComPtr<IProgress> progress; + CHECK_ERROR_BREAK(pAppliance, + ImportMachines(ComSafeArrayAsInParam(options), progress.asOutParam())); + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Appliance::tr("Appliance import failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Appliance::tr("Successfully imported the appliance.\n")); + } + } // end if (aVirtualSystemDescriptions.size() > 0) + } while (0); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static int parseExportOptions(const char *psz, com::SafeArray<ExportOptions_T> *options) +{ + int vrc = VINF_SUCCESS; + while (psz && *psz && RT_SUCCESS(vrc)) + { + size_t len; + const char *pszComma = strchr(psz, ','); + if (pszComma) + len = pszComma - psz; + else + len = strlen(psz); + if (len > 0) + { + if (!RTStrNICmp(psz, "CreateManifest", len)) + options->push_back(ExportOptions_CreateManifest); + else if (!RTStrNICmp(psz, "manifest", len)) + options->push_back(ExportOptions_CreateManifest); + else if (!RTStrNICmp(psz, "ExportDVDImages", len)) + options->push_back(ExportOptions_ExportDVDImages); + else if (!RTStrNICmp(psz, "iso", len)) + options->push_back(ExportOptions_ExportDVDImages); + else if (!RTStrNICmp(psz, "StripAllMACs", len)) + options->push_back(ExportOptions_StripAllMACs); + else if (!RTStrNICmp(psz, "nomacs", len)) + options->push_back(ExportOptions_StripAllMACs); + else if (!RTStrNICmp(psz, "StripAllNonNATMACs", len)) + options->push_back(ExportOptions_StripAllNonNATMACs); + else if (!RTStrNICmp(psz, "nomacsbutnat", len)) + options->push_back(ExportOptions_StripAllNonNATMACs); + else + vrc = VERR_PARSE_ERROR; + } + if (pszComma) + psz += len + 1; + else + psz += len; + } + + return vrc; +} + +static const RTGETOPTDEF g_aExportOptions[] = +{ + { "--output", 'o', RTGETOPT_REQ_STRING }, + { "--legacy09", 'l', RTGETOPT_REQ_NOTHING }, + { "--ovf09", 'l', RTGETOPT_REQ_NOTHING }, + { "--ovf10", '1', RTGETOPT_REQ_NOTHING }, + { "--ovf20", '2', RTGETOPT_REQ_NOTHING }, + { "--opc10", 'c', RTGETOPT_REQ_NOTHING }, + { "--manifest", 'm', RTGETOPT_REQ_NOTHING }, // obsoleted by --options + { "--vsys", 's', RTGETOPT_REQ_UINT32 }, + { "--vmname", 'V', RTGETOPT_REQ_STRING }, + { "--product", 'p', RTGETOPT_REQ_STRING }, + { "--producturl", 'P', RTGETOPT_REQ_STRING }, + { "--vendor", 'n', RTGETOPT_REQ_STRING }, + { "--vendorurl", 'N', RTGETOPT_REQ_STRING }, + { "--version", 'v', RTGETOPT_REQ_STRING }, + { "--description", 'd', RTGETOPT_REQ_STRING }, + { "--eula", 'e', RTGETOPT_REQ_STRING }, + { "--eulafile", 'E', RTGETOPT_REQ_STRING }, + { "--options", 'O', RTGETOPT_REQ_STRING }, + { "--cloud", 'C', RTGETOPT_REQ_UINT32 }, + { "--cloudshape", 'S', RTGETOPT_REQ_STRING }, + { "--clouddomain", 'D', RTGETOPT_REQ_STRING }, + { "--clouddisksize", 'R', RTGETOPT_REQ_STRING }, + { "--cloudbucket", 'B', RTGETOPT_REQ_STRING }, + { "--cloudocivcn", 'Q', RTGETOPT_REQ_STRING }, + { "--cloudpublicip", 'A', RTGETOPT_REQ_STRING }, + { "--cloudprofile", 'F', RTGETOPT_REQ_STRING }, + { "--cloudocisubnet", 'T', RTGETOPT_REQ_STRING }, + { "--cloudkeepobject", 'K', RTGETOPT_REQ_STRING }, + { "--cloudlaunchinstance", 'L', RTGETOPT_REQ_STRING }, + { "--cloudlaunchmode", 'M', RTGETOPT_REQ_STRING }, + { "--cloudprivateip", 'i', RTGETOPT_REQ_STRING }, + { "--cloudinitscriptpath", 'I', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleExportAppliance(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + Utf8Str strOutputFile; + Utf8Str strOvfFormat("ovf-1.0"); // the default export version + bool fManifest = false; // the default + APPLIANCETYPE enmApplType = NOT_SET; + bool fExportISOImages = false; // the default + com::SafeArray<ExportOptions_T> options; + std::list< ComPtr<IMachine> > llMachines; + + uint32_t ulCurVsys = (uint32_t)-1; + // for each --vsys X command, maintain a map of command line items + ArgsMapsMap mapArgsMapsPerVsys; + do + { + int c; + + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aExportOptions, + RT_ELEMENTS(g_aExportOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + + Utf8Str strProductUrl; + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'o': // --output + if (strOutputFile.length()) + return errorSyntax(Appliance::tr("You can only specify --output once.")); + else + strOutputFile = ValueUnion.psz; + break; + + case 'l': // --legacy09/--ovf09 + strOvfFormat = "ovf-0.9"; + break; + + case '1': // --ovf10 + strOvfFormat = "ovf-1.0"; + break; + + case '2': // --ovf20 + strOvfFormat = "ovf-2.0"; + break; + + case 'c': // --opc + strOvfFormat = "opc-1.0"; + break; + +// case 'I': // --iso +// fExportISOImages = true; +// break; + + case 'm': // --manifest + fManifest = true; + break; + + case 's': // --vsys + if (enmApplType == NOT_SET) + enmApplType = LOCAL; + + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" can't be used together with \"--cloud\" option."), + GetState.pDef->pszLong); + if (ValueUnion.u32 == (uint32_t)-1) + return errorSyntax(Appliance::tr("Value of option \"%s\" is out of range."), + GetState.pDef->pszLong); + + ulCurVsys = ValueUnion.u32; + break; + + case 'V': // --vmname + if (enmApplType == NOT_SET) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys or --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["vmname"] = ValueUnion.psz; + break; + + case 'p': // --product + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["product"] = ValueUnion.psz; + break; + + case 'P': // --producturl + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["producturl"] = ValueUnion.psz; + break; + + case 'n': // --vendor + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["vendor"] = ValueUnion.psz; + break; + + case 'N': // --vendorurl + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["vendorurl"] = ValueUnion.psz; + break; + + case 'v': // --version + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["version"] = ValueUnion.psz; + break; + + case 'd': // --description + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["description"] = ValueUnion.psz; + break; + + case 'e': // --eula + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["eula"] = ValueUnion.psz; + break; + + case 'E': // --eulafile + if (enmApplType != LOCAL) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --vsys option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["eulafile"] = ValueUnion.psz; + break; + + case 'O': // --options + if (RT_FAILURE(parseExportOptions(ValueUnion.psz, &options))) + return errorArgument(Appliance::tr("Invalid export options '%s'\n"), ValueUnion.psz); + break; + + /*--cloud and --vsys are orthogonal, only one must be presented*/ + case 'C': // --cloud + if (enmApplType == NOT_SET) + enmApplType = CLOUD; + + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" can't be used together with \"--vsys\" option."), + GetState.pDef->pszLong); + if (ValueUnion.u32 == (uint32_t)-1) + return errorSyntax(Appliance::tr("Value of option \"%s\" is out of range."), + GetState.pDef->pszLong); + + ulCurVsys = ValueUnion.u32; + break; + + /* Cloud export settings */ + case 'S': // --cloudshape + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudshape"] = ValueUnion.psz; + break; + + case 'D': // --clouddomain + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["clouddomain"] = ValueUnion.psz; + break; + + case 'R': // --clouddisksize + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["clouddisksize"] = ValueUnion.psz; + break; + + case 'B': // --cloudbucket + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudbucket"] = ValueUnion.psz; + break; + + case 'Q': // --cloudocivcn + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudocivcn"] = ValueUnion.psz; + break; + + case 'A': // --cloudpublicip + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudpublicip"] = ValueUnion.psz; + break; + + case 'i': /* --cloudprivateip */ + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudprivateip"] = ValueUnion.psz; + break; + + case 'F': // --cloudprofile + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudprofile"] = ValueUnion.psz; + break; + + case 'T': // --cloudocisubnet + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudocisubnet"] = ValueUnion.psz; + break; + + case 'K': // --cloudkeepobject + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudkeepobject"] = ValueUnion.psz; + break; + + case 'L': // --cloudlaunchinstance + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudlaunchinstance"] = ValueUnion.psz; + break; + + case 'M': /* --cloudlaunchmode */ + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudlaunchmode"] = ValueUnion.psz; + break; + + case 'I': // --cloudinitscriptpath + if (enmApplType != CLOUD) + return errorSyntax(Appliance::tr("Option \"%s\" requires preceding --cloud option."), + GetState.pDef->pszLong); + mapArgsMapsPerVsys[ulCurVsys]["cloudinitscriptpath"] = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + { + Utf8Str strMachine(ValueUnion.psz); + // must be machine: try UUID or name + ComPtr<IMachine> machine; + CHECK_ERROR_BREAK(a->virtualBox, FindMachine(Bstr(strMachine).raw(), + machine.asOutParam())); + if (machine) + llMachines.push_back(machine); + break; + } + + default: + if (c > 0) + { + if (RT_C_IS_GRAPH(c)) + return errorSyntax(Appliance::tr("unhandled option: -%c"), c); + else + return errorSyntax(Appliance::tr("unhandled option: %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Appliance::tr("unknown option: %s"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax("%Rrs", c); + } + + if (FAILED(hrc)) + break; + } + + if (FAILED(hrc)) + break; + + if (llMachines.empty()) + return errorSyntax(Appliance::tr("At least one machine must be specified with the export command.")); + + /* Last check after parsing all arguments */ + if (strOutputFile.isEmpty()) + return errorSyntax(Appliance::tr("Missing --output argument with export command.")); + + if (enmApplType == NOT_SET) + enmApplType = LOCAL; + + // match command line arguments with the machines count + // this is only to sort out invalid indices at this time + ArgsMapsMap::const_iterator it; + for (it = mapArgsMapsPerVsys.begin(); + it != mapArgsMapsPerVsys.end(); + ++it) + { + uint32_t ulVsys = it->first; + if (ulVsys >= llMachines.size()) + return errorSyntax(Appliance::tr("Invalid index %RI32 with -vsys option; you specified only %zu virtual system(s).", + "", llMachines.size()), + ulVsys, llMachines.size()); + } + + ComPtr<IAppliance> pAppliance; + CHECK_ERROR_BREAK(a->virtualBox, CreateAppliance(pAppliance.asOutParam())); + + char *pszAbsFilePath = 0; + if (strOutputFile.startsWith("S3://", RTCString::CaseInsensitive) || + strOutputFile.startsWith("SunCloud://", RTCString::CaseInsensitive) || + strOutputFile.startsWith("webdav://", RTCString::CaseInsensitive) || + strOutputFile.startsWith("OCI://", RTCString::CaseInsensitive)) + pszAbsFilePath = RTStrDup(strOutputFile.c_str()); + else + pszAbsFilePath = RTPathAbsDup(strOutputFile.c_str()); + + /* + * The first stage - export machine/s to the Cloud or into the + * OVA/OVF format on the local host. + */ + + /* VSDList is needed for the second stage where we launch the cloud instances if it was requested by user */ + std::list< ComPtr<IVirtualSystemDescription> > VSDList; + std::list< ComPtr<IMachine> >::iterator itM; + uint32_t i=0; + for (itM = llMachines.begin(); + itM != llMachines.end(); + ++itM, ++i) + { + ComPtr<IMachine> pMachine = *itM; + ComPtr<IVirtualSystemDescription> pVSD; + CHECK_ERROR_BREAK(pMachine, ExportTo(pAppliance, Bstr(pszAbsFilePath).raw(), pVSD.asOutParam())); + + // Add additional info to the virtual system description if the user wants so + ArgsMap *pmapArgs = NULL; + ArgsMapsMap::iterator itm = mapArgsMapsPerVsys.find(i); + if (itm != mapArgsMapsPerVsys.end()) + pmapArgs = &itm->second; + if (pmapArgs) + { + ArgsMap::iterator itD; + for (itD = pmapArgs->begin(); + itD != pmapArgs->end(); + ++itD) + { + if (itD->first == "vmname") + { + //remove default value if user has specified new name (default value is set in the ExportTo()) +// pVSD->RemoveDescriptionByType(VirtualSystemDescriptionType_Name); + pVSD->AddDescription(VirtualSystemDescriptionType_Name, + Bstr(itD->second).raw(), NULL); + } + else if (itD->first == "product") + pVSD->AddDescription(VirtualSystemDescriptionType_Product, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "producturl") + pVSD->AddDescription(VirtualSystemDescriptionType_ProductUrl, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "vendor") + pVSD->AddDescription(VirtualSystemDescriptionType_Vendor, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "vendorurl") + pVSD->AddDescription(VirtualSystemDescriptionType_VendorUrl, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "version") + pVSD->AddDescription(VirtualSystemDescriptionType_Version, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "description") + pVSD->AddDescription(VirtualSystemDescriptionType_Description, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "eula") + pVSD->AddDescription(VirtualSystemDescriptionType_License, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "eulafile") + { + Utf8Str strContent; + void *pvFile; + size_t cbFile; + int irc = RTFileReadAll(itD->second.c_str(), &pvFile, &cbFile); + if (RT_SUCCESS(irc)) + { + Bstr bstrContent((char*)pvFile, cbFile); + pVSD->AddDescription(VirtualSystemDescriptionType_License, + bstrContent.raw(), NULL); + RTFileReadAllFree(pvFile, cbFile); + } + else + { + RTMsgError(Appliance::tr("Cannot read license file \"%s\" which should be included in the virtual system %u."), + itD->second.c_str(), i); + return RTEXITCODE_FAILURE; + } + } + /* add cloud export settings */ + else if (itD->first == "cloudshape") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudInstanceShape, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "clouddomain") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudDomain, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "clouddisksize") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootDiskSize, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudbucket") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudBucket, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudocivcn") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCIVCN, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudpublicip") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicIP, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudprivateip") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudPrivateIP, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudprofile") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudProfileName, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudocisubnet") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCISubnet, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudkeepobject") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudKeepObject, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudlaunchmode") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCILaunchMode, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudlaunchinstance") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudLaunchInstance, + Bstr(itD->second).raw(), NULL); + else if (itD->first == "cloudinitscriptpath") + pVSD->AddDescription(VirtualSystemDescriptionType_CloudInitScriptPath, + Bstr(itD->second).raw(), NULL); + + } + } + + VSDList.push_back(pVSD);//store vsd for the possible second stage + } + + if (FAILED(hrc)) + break; + + /* Query required passwords and supply them to the appliance. */ + com::SafeArray<BSTR> aIdentifiers; + + CHECK_ERROR_BREAK(pAppliance, GetPasswordIds(ComSafeArrayAsOutParam(aIdentifiers))); + + if (aIdentifiers.size() > 0) + { + com::SafeArray<BSTR> aPasswords(aIdentifiers.size()); + RTPrintf(Appliance::tr("Enter the passwords for the following identifiers to export the apppliance:\n")); + for (unsigned idxId = 0; idxId < aIdentifiers.size(); idxId++) + { + com::Utf8Str strPassword; + Bstr bstrPassword; + Bstr bstrId = aIdentifiers[idxId]; + + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, Appliance::tr("Password ID %s:"), + Utf8Str(bstrId).c_str()); + if (rcExit == RTEXITCODE_FAILURE) + { + RTStrFree(pszAbsFilePath); + return rcExit; + } + + bstrPassword = strPassword; + bstrPassword.detachTo(&aPasswords[idxId]); + } + + CHECK_ERROR_BREAK(pAppliance, AddPasswords(ComSafeArrayAsInParam(aIdentifiers), + ComSafeArrayAsInParam(aPasswords))); + } + + if (fManifest) + options.push_back(ExportOptions_CreateManifest); + + if (fExportISOImages) + options.push_back(ExportOptions_ExportDVDImages); + + ComPtr<IProgress> progress; + CHECK_ERROR_BREAK(pAppliance, Write(Bstr(strOvfFormat).raw(), + ComSafeArrayAsInParam(options), + Bstr(pszAbsFilePath).raw(), + progress.asOutParam())); + RTStrFree(pszAbsFilePath); + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Appliance::tr("Appliance write failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Appliance::tr("Successfully exported %d machine(s).\n", "", llMachines.size()), llMachines.size()); + + /* + * The second stage for the cloud case + */ + if (enmApplType == CLOUD) + { + /* Launch the exported VM if the appropriate flag had been set on the first stage */ + for (std::list< ComPtr<IVirtualSystemDescription> >::iterator itVSD = VSDList.begin(); + itVSD != VSDList.end(); + ++itVSD) + { + ComPtr<IVirtualSystemDescription> pVSD = *itVSD; + + com::SafeArray<VirtualSystemDescriptionType_T> retTypes; + com::SafeArray<BSTR> aRefs; + com::SafeArray<BSTR> aOvfValues; + com::SafeArray<BSTR> aVBoxValues; + com::SafeArray<BSTR> aExtraConfigValues; + + CHECK_ERROR_BREAK(pVSD, GetDescriptionByType(VirtualSystemDescriptionType_CloudLaunchInstance, + ComSafeArrayAsOutParam(retTypes), + ComSafeArrayAsOutParam(aRefs), + ComSafeArrayAsOutParam(aOvfValues), + ComSafeArrayAsOutParam(aVBoxValues), + ComSafeArrayAsOutParam(aExtraConfigValues))); + + Utf8Str flagCloudLaunchInstance(Bstr(aVBoxValues[0]).raw()); + retTypes.setNull(); aRefs.setNull(); aOvfValues.setNull(); aVBoxValues.setNull(); aExtraConfigValues.setNull(); + + if (flagCloudLaunchInstance.equals("true")) + { + /* Getting the short provider name */ + Bstr bstrCloudProviderShortName(strOutputFile.c_str(), strOutputFile.find("://")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR_BREAK(pVirtualBox, COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam())); + + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR_BREAK(pCloudProviderManager, + GetProviderByShortName(bstrCloudProviderShortName.raw(), pCloudProvider.asOutParam())); + + CHECK_ERROR_BREAK(pVSD, GetDescriptionByType(VirtualSystemDescriptionType_CloudProfileName, + ComSafeArrayAsOutParam(retTypes), + ComSafeArrayAsOutParam(aRefs), + ComSafeArrayAsOutParam(aOvfValues), + ComSafeArrayAsOutParam(aVBoxValues), + ComSafeArrayAsOutParam(aExtraConfigValues))); + + ComPtr<ICloudProfile> pCloudProfile; + CHECK_ERROR_BREAK(pCloudProvider, GetProfileByName(Bstr(aVBoxValues[0]).raw(), pCloudProfile.asOutParam())); + retTypes.setNull(); aRefs.setNull(); aOvfValues.setNull(); aVBoxValues.setNull(); aExtraConfigValues.setNull(); + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR_BREAK(pCloudProfile, CreateCloudClient(oCloudClient.asOutParam())); + RTPrintf(Appliance::tr("Creating a cloud instance...\n")); + + ComPtr<IProgress> progress1; + CHECK_ERROR_BREAK(oCloudClient, LaunchVM(pVSD, progress1.asOutParam())); + hrc = showProgress(progress1); + CHECK_PROGRESS_ERROR_RET(progress1, (Appliance::tr("Creating the cloud instance failed")), + RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + { + CHECK_ERROR_BREAK(pVSD, GetDescriptionByType(VirtualSystemDescriptionType_CloudInstanceId, + ComSafeArrayAsOutParam(retTypes), + ComSafeArrayAsOutParam(aRefs), + ComSafeArrayAsOutParam(aOvfValues), + ComSafeArrayAsOutParam(aVBoxValues), + ComSafeArrayAsOutParam(aExtraConfigValues))); + + RTPrintf(Appliance::tr("A cloud instance with id '%s' (provider '%s') was created\n"), + Utf8Str(Bstr(aVBoxValues[0]).raw()).c_str(), + Utf8Str(bstrCloudProviderShortName.raw()).c_str()); + retTypes.setNull(); aRefs.setNull(); aOvfValues.setNull(); aVBoxValues.setNull(); aExtraConfigValues.setNull(); + } + } + } + } + } while (0); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/********************************************************************************************************************************* +* signova * +*********************************************************************************************************************************/ + +/** + * Reads the OVA and saves the manifest and signed status. + * + * @returns VBox status code (fully messaged). + * @param pszOva The name of the OVA. + * @param iVerbosity The noise level. + * @param fReSign Whether it is acceptable to have an existing signature + * in the OVA or not. + * @param phVfsFssOva Where to return the OVA file system stream handle. + * This has been opened for updating and we're positioned + * at the end of the stream. + * @param pStrManifestName Where to return the manifest name. + * @param phVfsManifest Where to return the manifest file handle (copy in mem). + * @param phVfsOldSignature Where to return the handle to the old signature object. + * + * @note Caller must clean up return values on failure too! + */ +static int openOvaAndGetManifestAndOldSignature(const char *pszOva, unsigned iVerbosity, bool fReSign, + PRTVFSFSSTREAM phVfsFssOva, Utf8Str *pStrManifestName, + PRTVFSFILE phVfsManifest, PRTVFSOBJ phVfsOldSignature) +{ + /* + * Clear return values. + */ + *phVfsFssOva = NIL_RTVFSFSSTREAM; + pStrManifestName->setNull(); + *phVfsManifest = NIL_RTVFSFILE; + *phVfsOldSignature = NIL_RTVFSOBJ; + + /* + * Open the file as a tar file system stream. + */ + RTVFSFILE hVfsFileOva; + int vrc = RTVfsFileOpenNormal(pszOva, RTFILE_O_OPEN | RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE, &hVfsFileOva); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Appliance::tr("Failed to open OVA '%s' for updating: %Rrc"), pszOva, vrc); + + RTVFSFSSTREAM hVfsFssOva; + vrc = RTZipTarFsStreamForFile(hVfsFileOva, RTZIPTARFORMAT_DEFAULT, RTZIPTAR_C_UPDATE, &hVfsFssOva); + RTVfsFileRelease(hVfsFileOva); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Appliance::tr("Failed to open OVA '%s' as a TAR file: %Rrc"), pszOva, vrc); + *phVfsFssOva = hVfsFssOva; + + /* + * Scan the objects in the stream and locate the manifest and any existing cert file. + */ + if (iVerbosity >= 2) + RTMsgInfo(Appliance::tr("Scanning OVA '%s' for a manifest and signature..."), pszOva); + char *pszSignatureName = NULL; + for (;;) + { + /* + * Retrive the next object. + */ + char *pszName; + RTVFSOBJTYPE enmType; + RTVFSOBJ hVfsObj; + vrc = RTVfsFsStrmNext(hVfsFssOva, &pszName, &enmType, &hVfsObj); + if (RT_FAILURE(vrc)) + { + if (vrc == VERR_EOF) + vrc = VINF_SUCCESS; + else + RTMsgError(Appliance::tr("RTVfsFsStrmNext returned %Rrc"), vrc); + break; + } + + if (iVerbosity > 2) + RTMsgInfo(" %s %s\n", RTVfsTypeName(enmType), pszName); + + /* + * Should we process this entry? + */ + const char *pszSuffix = RTPathSuffix(pszName); + if ( pszSuffix + && RTStrICmpAscii(pszSuffix, ".mf") == 0 + && (enmType == RTVFSOBJTYPE_IO_STREAM || enmType == RTVFSOBJTYPE_FILE)) + { + if (*phVfsManifest != NIL_RTVFSFILE) + vrc = RTMsgErrorRc(VERR_DUPLICATE, Appliance::tr("OVA contains multiple manifests! first: %s second: %s"), + pStrManifestName->c_str(), pszName); + else if (pszSignatureName) + vrc = RTMsgErrorRc(VERR_WRONG_ORDER, + Appliance::tr("Unsupported OVA file ordering! Signature file ('%s') as succeeded by '%s'."), + pszSignatureName, pszName); + else + { + if (iVerbosity >= 2) + RTMsgInfo(Appliance::tr("Found manifest file: %s"), pszName); + vrc = pStrManifestName->assignNoThrow(pszName); + if (RT_SUCCESS(vrc)) + { + RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(hVfsObj); + Assert(hVfsIos != NIL_RTVFSIOSTREAM); + vrc = RTVfsMemorizeIoStreamAsFile(hVfsIos, RTFILE_O_READ, phVfsManifest); + RTVfsIoStrmRelease(hVfsIos); /* consumes stream handle. */ + if (RT_FAILURE(vrc)) + vrc = RTMsgErrorRc(VERR_DUPLICATE, Appliance::tr("Failed to memorize the manifest: %Rrc"), vrc); + } + else + RTMsgError(Appliance::tr("Out of memory!")); + } + } + else if ( pszSuffix + && RTStrICmpAscii(pszSuffix, ".cert") == 0 + && (enmType == RTVFSOBJTYPE_IO_STREAM || enmType == RTVFSOBJTYPE_FILE)) + { + if (*phVfsOldSignature != NIL_RTVFSOBJ) + vrc = RTMsgErrorRc(VERR_WRONG_ORDER, Appliance::tr("Multiple signature files! (%s)"), pszName); + else + { + if (iVerbosity >= 2) + RTMsgInfo(Appliance::tr("Found existing signature file: %s"), pszName); + pszSignatureName = pszName; + *phVfsOldSignature = hVfsObj; + pszName = NULL; + hVfsObj = NIL_RTVFSOBJ; + } + } + else if (pszSignatureName) + vrc = RTMsgErrorRc(VERR_WRONG_ORDER, + Appliance::tr("Unsupported OVA file ordering! Signature file ('%s') as succeeded by '%s'."), + pszSignatureName, pszName); + + /* + * Release the current object and string. + */ + RTVfsObjRelease(hVfsObj); + RTStrFree(pszName); + if (RT_FAILURE(vrc)) + break; + } + + /* + * Complain if no manifest. + */ + if (RT_SUCCESS(vrc) && *phVfsManifest == NIL_RTVFSFILE) + vrc = RTMsgErrorRc(VERR_NOT_FOUND, Appliance::tr("The OVA contains no manifest and cannot be signed!")); + else if (RT_SUCCESS(vrc) && *phVfsOldSignature != NIL_RTVFSOBJ && !fReSign) + vrc = RTMsgErrorRc(VERR_ALREADY_EXISTS, + Appliance::tr("The OVA is already signed ('%s')! (Use the --force option to force re-signing it.)"), + pszSignatureName); + + RTStrFree(pszSignatureName); + return vrc; +} + + +/** + * Continues where openOvaAndGetManifestAndOldSignature() left off and writes + * the signature file to the OVA. + * + * When @a hVfsOldSignature isn't NIL, the old signature it represent will be + * replaced. The open function has already made sure there isn't anything + * following the .cert file in that case. + */ +static int updateTheOvaSignature(RTVFSFSSTREAM hVfsFssOva, const char *pszOva, const char *pszSignatureName, + RTVFSFILE hVfsFileSignature, RTVFSOBJ hVfsOldSignature, unsigned iVerbosity) +{ + if (iVerbosity > 1) + RTMsgInfo(Appliance::tr("Writing '%s' to the OVA..."), pszSignatureName); + + /* + * Truncate the file at the old signature, if present. + */ + int vrc; + if (hVfsOldSignature != NIL_RTVFSOBJ) + { + vrc = RTZipTarFsStreamTruncate(hVfsFssOva, hVfsOldSignature, false /*fAfter*/); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, Appliance::tr("RTZipTarFsStreamTruncate failed on '%s': %Rrc"), pszOva, vrc); + } + + /* + * Append the signature file. We have to rewind it first or + * we'll end up with VERR_EOF, probably not a great idea... + */ + vrc = RTVfsFileSeek(hVfsFileSignature, 0, RTFILE_SEEK_BEGIN, NULL); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, Appliance::tr("RTVfsFileSeek(hVfsFileSignature) failed: %Rrc"), vrc); + + RTVFSOBJ hVfsObj = RTVfsObjFromFile(hVfsFileSignature); + vrc = RTVfsFsStrmAdd(hVfsFssOva, pszSignatureName, hVfsObj, 0 /*fFlags*/); + RTVfsObjRelease(hVfsObj); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, Appliance::tr("RTVfsFsStrmAdd('%s') failed on '%s': %Rrc"), pszSignatureName, pszOva, vrc); + + /* + * Terminate the file system stream. + */ + vrc = RTVfsFsStrmEnd(hVfsFssOva); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, Appliance::tr("RTVfsFsStrmEnd failed on '%s': %Rrc"), pszOva, vrc); + + return VINF_SUCCESS; +} + + +/** + * Worker for doCheckPkcs7Signature. + */ +static int doCheckPkcs7SignatureWorker(PRTCRPKCS7CONTENTINFO pContentInfo, void const *pvManifest, size_t cbManifest, + unsigned iVerbosity, const char *pszTag, PRTERRINFOSTATIC pErrInfo) +{ + int vrc; + + /* + * It must be signedData. + */ + if (RTCrPkcs7ContentInfo_IsSignedData(pContentInfo)) + { + PRTCRPKCS7SIGNEDDATA pSignedData = pContentInfo->u.pSignedData; + + /* + * Inside the signedData there must be just 'data'. + */ + if (!strcmp(pSignedData->ContentInfo.ContentType.szObjId, RTCR_PKCS7_DATA_OID)) + { + /* + * Check that things add up. + */ + vrc = RTCrPkcs7SignedData_CheckSanity(pSignedData, + RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH + | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT, + RTErrInfoInitStatic(pErrInfo), "SD"); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 2 && pszTag == NULL) + RTMsgInfo(Appliance::tr(" Successfully decoded the PKCS#7/CMS signature...")); + + /* + * Check that we can verify the signed data, but skip certificate validate as + * we probably don't necessarily have the correct root certs handy here. + */ + RTTIMESPEC Now; + vrc = RTCrPkcs7VerifySignedDataWithExternalData(pContentInfo, RTCRPKCS7VERIFY_SD_F_TRUST_ALL_CERTS, + NIL_RTCRSTORE /*hAdditionalCerts*/, + NIL_RTCRSTORE /*hTrustedCerts*/, + RTTimeNow(&Now), + NULL /*pfnVerifyCert*/, NULL /*pvUser*/, + pvManifest, cbManifest, RTErrInfoInitStatic(pErrInfo)); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 1 && pszTag != NULL) + RTMsgInfo(Appliance::tr(" Successfully verified the PKCS#7/CMS signature")); + } + else + vrc = RTMsgErrorRc(vrc, Appliance::tr("Failed to verify the PKCS#7/CMS signature: %Rrc%RTeim"), + vrc, &pErrInfo->Core); + } + else + RTMsgError(Appliance::tr("RTCrPkcs7SignedData_CheckSanity failed on PKCS#7/CMS signature: %Rrc%RTeim"), + vrc, &pErrInfo->Core); + + } + else + vrc = RTMsgErrorRc(VERR_WRONG_TYPE, Appliance::tr("PKCS#7/CMS signature inner ContentType isn't 'data' but: %s"), + pSignedData->ContentInfo.ContentType.szObjId); + } + else + vrc = RTMsgErrorRc(VERR_WRONG_TYPE, Appliance::tr("PKCS#7/CMD signature is not 'signedData': %s"), + pContentInfo->ContentType.szObjId); + return vrc; +} + +/** + * For testing the decoding side. + */ +static int doCheckPkcs7Signature(void const *pvSignature, size_t cbSignature, PCRTCRX509CERTIFICATE pCertificate, + RTCRSTORE hIntermediateCerts, void const *pvManifest, size_t cbManifest, + unsigned iVerbosity, PRTERRINFOSTATIC pErrInfo) +{ + RT_NOREF(pCertificate, hIntermediateCerts); + + RTASN1CURSORPRIMARY PrimaryCursor; + RTAsn1CursorInitPrimary(&PrimaryCursor, pvSignature, (uint32_t)cbSignature, RTErrInfoInitStatic(pErrInfo), + &g_RTAsn1DefaultAllocator, 0, "Signature"); + + RTCRPKCS7CONTENTINFO ContentInfo; + RT_ZERO(ContentInfo); + int vrc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &ContentInfo, "CI"); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 5) + RTAsn1Dump(&ContentInfo.SeqCore.Asn1Core, 0 /*fFlags*/, 0 /*uLevel*/, RTStrmDumpPrintfV, g_pStdOut); + + vrc = doCheckPkcs7SignatureWorker(&ContentInfo, pvManifest, cbManifest, iVerbosity, NULL, pErrInfo); + if (RT_SUCCESS(vrc)) + { + /* + * Clone it and repeat. This is to catch IPRT paths assuming + * that encoded data is always on hand. + */ + RTCRPKCS7CONTENTINFO ContentInfo2; + vrc = RTCrPkcs7ContentInfo_Clone(&ContentInfo2, &ContentInfo, &g_RTAsn1DefaultAllocator); + if (RT_SUCCESS(vrc)) + { + vrc = doCheckPkcs7SignatureWorker(&ContentInfo2, pvManifest, cbManifest, iVerbosity, "cloned", pErrInfo); + RTCrPkcs7ContentInfo_Delete(&ContentInfo2); + } + else + vrc = RTMsgErrorRc(vrc, Appliance::tr("RTCrPkcs7ContentInfo_Clone failed: %Rrc"), vrc); + } + } + else + RTMsgError(Appliance::tr("RTCrPkcs7ContentInfo_DecodeAsn1 failed to decode PKCS#7/CMS signature: %Rrc%RTemi"), + vrc, &pErrInfo->Core); + + RTCrPkcs7ContentInfo_Delete(&ContentInfo); + return vrc; +} + + +/** + * Creates a PKCS\#7 signature and appends it to the signature file in PEM + * format. + */ +static int doAddPkcs7Signature(PCRTCRX509CERTIFICATE pCertificate, RTCRKEY hPrivateKey, RTDIGESTTYPE enmDigestType, + unsigned cIntermediateCerts, const char **papszIntermediateCerts, RTVFSFILE hVfsFileManifest, + unsigned iVerbosity, PRTERRINFOSTATIC pErrInfo, RTVFSFILE hVfsFileSignature) +{ + /* + * Add a blank line, just for good measure. + */ + int vrc = RTVfsFileWrite(hVfsFileSignature, "\n", 1, NULL); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, "RTVfsFileWrite/signature: %Rrc", vrc); + + /* + * Read the manifest into a single memory block. + */ + uint64_t cbManifest; + vrc = RTVfsFileQuerySize(hVfsFileManifest, &cbManifest); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, "RTVfsFileQuerySize/manifest: %Rrc", vrc); + if (cbManifest > _4M) + return RTMsgErrorRc(VERR_OUT_OF_RANGE, Appliance::tr("Manifest is too big: %#RX64 bytes, max 4MiB", "", cbManifest), + cbManifest); + + void *pvManifest = RTMemAllocZ(cbManifest + 1); + if (!pvManifest) + return RTMsgErrorRc(VERR_NO_MEMORY, Appliance::tr("Out of memory!")); + + vrc = RTVfsFileReadAt(hVfsFileManifest, 0, pvManifest, (size_t)cbManifest, NULL); + if (RT_SUCCESS(vrc)) + { + /* + * Load intermediate certificates. + */ + RTCRSTORE hIntermediateCerts = NIL_RTCRSTORE; + if (cIntermediateCerts) + { + vrc = RTCrStoreCreateInMem(&hIntermediateCerts, cIntermediateCerts); + if (RT_SUCCESS(vrc)) + { + for (unsigned i = 0; i < cIntermediateCerts; i++) + { + const char *pszFile = papszIntermediateCerts[i]; + vrc = RTCrStoreCertAddFromFile(hIntermediateCerts, 0 /*fFlags*/, pszFile, &pErrInfo->Core); + if (RT_FAILURE(vrc)) + { + RTMsgError(Appliance::tr("RTCrStoreCertAddFromFile failed on '%s': %Rrc%#RTeim"), + pszFile, vrc, &pErrInfo->Core); + break; + } + } + } + else + RTMsgError(Appliance::tr("RTCrStoreCreateInMem failed: %Rrc"), vrc); + } + if (RT_SUCCESS(vrc)) + { + /* + * Do a dry run to determin the size of the signed data. + */ + size_t cbResult = 0; + vrc = RTCrPkcs7SimpleSignSignedData(RTCRPKCS7SIGN_SD_F_DEATCHED | RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP, + pCertificate, hPrivateKey, pvManifest, (size_t)cbManifest, enmDigestType, + hIntermediateCerts, NULL /*pAdditionalAuthenticatedAttribs*/, + NULL /*pvResult*/, &cbResult, RTErrInfoInitStatic(pErrInfo)); + if (vrc == VERR_BUFFER_OVERFLOW) + { + /* + * Allocate a buffer of the right size and do the real run. + */ + void *pvResult = RTMemAllocZ(cbResult); + if (pvResult) + { + vrc = RTCrPkcs7SimpleSignSignedData(RTCRPKCS7SIGN_SD_F_DEATCHED | RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP, + pCertificate, hPrivateKey, pvManifest, (size_t)cbManifest, enmDigestType, + hIntermediateCerts, NULL /*pAdditionalAuthenticatedAttribs*/, + pvResult, &cbResult, RTErrInfoInitStatic(pErrInfo)); + if (RT_SUCCESS(vrc)) + { + /* + * Add it to the signature file in PEM format. + */ + vrc = (int)RTCrPemWriteBlobToVfsFile(hVfsFileSignature, pvResult, cbResult, "CMS"); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 1) + RTMsgInfo(Appliance::tr("Created PKCS#7/CMS signature: %zu bytes, %s.", "", cbResult), + cbResult, RTCrDigestTypeToName(enmDigestType)); + if (enmDigestType == RTDIGESTTYPE_SHA1) + RTMsgWarning(Appliance::tr("Using SHA-1 instead of SHA-3 for the PKCS#7/CMS signature.")); + + /* + * Try decode and verify the signature. + */ + vrc = doCheckPkcs7Signature(pvResult, cbResult, pCertificate, hIntermediateCerts, + pvManifest, (size_t)cbManifest, iVerbosity, pErrInfo); + } + else + RTMsgError(Appliance::tr("RTCrPemWriteBlobToVfsFile failed: %Rrc"), vrc); + } + RTMemFree(pvResult); + } + else + vrc = RTMsgErrorRc(VERR_NO_MEMORY, Appliance::tr("Out of memory!")); + } + else + RTMsgError(Appliance::tr("RTCrPkcs7SimpleSignSignedData failed: %Rrc%#RTeim"), vrc, &pErrInfo->Core); + } + } + else + RTMsgError(Appliance::tr("RTVfsFileReadAt failed: %Rrc"), vrc); + RTMemFree(pvManifest); + return vrc; +} + + +/** + * Performs the OVA signing, producing an in-memory cert-file. + */ +static int doTheOvaSigning(PRTCRX509CERTIFICATE pCertificate, RTCRKEY hPrivateKey, RTDIGESTTYPE enmDigestType, + const char *pszManifestName, RTVFSFILE hVfsFileManifest, + bool fPkcs7, unsigned cIntermediateCerts, const char **papszIntermediateCerts, unsigned iVerbosity, + PRTERRINFOSTATIC pErrInfo, PRTVFSFILE phVfsFileSignature) +{ + /* + * Determine the digest types, preferring SHA-256 for the OVA signature + * and SHA-512 for the PKCS#7/CMS one. Try use different hashes for the two. + */ + if (enmDigestType == RTDIGESTTYPE_UNKNOWN) + { + if (RTCrPkixCanCertHandleDigestType(pCertificate, RTDIGESTTYPE_SHA256, NULL)) + enmDigestType = RTDIGESTTYPE_SHA256; + else + enmDigestType = RTDIGESTTYPE_SHA1; + } + + /* Try SHA-3 for better diversity, only fall back on SHA1 if the private + key doesn't have enough bits (we skip SHA2 as it has the same variants + and key size requirements as SHA-3). */ + RTDIGESTTYPE enmPkcs7DigestType; + if (RTCrPkixCanCertHandleDigestType(pCertificate, RTDIGESTTYPE_SHA3_512, NULL)) + enmPkcs7DigestType = RTDIGESTTYPE_SHA3_512; + else if (RTCrPkixCanCertHandleDigestType(pCertificate, RTDIGESTTYPE_SHA3_384, NULL)) + enmPkcs7DigestType = RTDIGESTTYPE_SHA3_384; + else if (RTCrPkixCanCertHandleDigestType(pCertificate, RTDIGESTTYPE_SHA3_256, NULL)) + enmPkcs7DigestType = RTDIGESTTYPE_SHA3_256; + else if (RTCrPkixCanCertHandleDigestType(pCertificate, RTDIGESTTYPE_SHA3_224, NULL)) + enmPkcs7DigestType = RTDIGESTTYPE_SHA3_224; + else + enmPkcs7DigestType = RTDIGESTTYPE_SHA1; + + /* + * Figure the string name for the .cert file. + */ + const char *pszDigestType; + switch (enmDigestType) + { + case RTDIGESTTYPE_SHA1: pszDigestType = "SHA1"; break; + case RTDIGESTTYPE_SHA256: pszDigestType = "SHA256"; break; + case RTDIGESTTYPE_SHA224: pszDigestType = "SHA224"; break; + case RTDIGESTTYPE_SHA512: pszDigestType = "SHA512"; break; + default: + return RTMsgErrorRc(VERR_INVALID_PARAMETER, + Appliance::tr("Unsupported digest type: %s"), RTCrDigestTypeToName(enmDigestType)); + } + + /* + * Digest the manifest file. + */ + RTCRDIGEST hDigest = NIL_RTCRDIGEST; + int vrc = RTCrDigestCreateByType(&hDigest, enmDigestType); + if (RT_FAILURE(vrc)) + return RTMsgErrorRc(vrc, Appliance::tr("Failed to create digest for %s: %Rrc"), RTCrDigestTypeToName(enmDigestType), vrc); + + vrc = RTCrDigestUpdateFromVfsFile(hDigest, hVfsFileManifest, true /*fRewindFile*/); + if (RT_SUCCESS(vrc)) + vrc = RTCrDigestFinal(hDigest, NULL, 0); + if (RT_SUCCESS(vrc)) + { + /* + * Sign the digest. Two passes, first to figure the signature size, the + * second to do the actual signing. + */ + PCRTASN1OBJID const pAlgorithm = &pCertificate->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm; + PCRTASN1DYNTYPE const pAlgoParams = &pCertificate->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Parameters; + size_t cbSignature = 0; + vrc = RTCrPkixPubKeySignDigest(pAlgorithm, hPrivateKey, pAlgoParams, hDigest, 0 /*fFlags*/, + NULL /*pvSignature*/, &cbSignature, RTErrInfoInitStatic(pErrInfo)); + if (vrc == VERR_BUFFER_OVERFLOW) + { + void *pvSignature = RTMemAllocZ(cbSignature); + if (pvSignature) + { + vrc = RTCrPkixPubKeySignDigest(pAlgorithm, hPrivateKey, pAlgoParams, hDigest, 0, + pvSignature, &cbSignature, RTErrInfoInitStatic(pErrInfo)); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 1) + RTMsgInfo(Appliance::tr("Created OVA signature: %zu bytes, %s", "", cbSignature), cbSignature, + RTCrDigestTypeToName(enmDigestType)); + + /* + * Verify the signature using the certificate to make sure we've + * been given the right private key. + */ + vrc = RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo(&pCertificate->TbsCertificate.SubjectPublicKeyInfo, + pvSignature, cbSignature, hDigest, + RTErrInfoInitStatic(pErrInfo)); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 2) + RTMsgInfo(Appliance::tr(" Successfully decoded and verified the OVA signature.\n")); + + /* + * Create the output file. + */ + RTVFSFILE hVfsFileSignature; + vrc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, _8K, &hVfsFileSignature); + if (RT_SUCCESS(vrc)) + { + vrc = (int)RTVfsFilePrintf(hVfsFileSignature, "%s(%s) = %#.*Rhxs\n\n", + pszDigestType, pszManifestName, cbSignature, pvSignature); + if (RT_SUCCESS(vrc)) + { + vrc = (int)RTCrX509Certificate_WriteToVfsFile(hVfsFileSignature, pCertificate, + RTErrInfoInitStatic(pErrInfo)); + if (RT_SUCCESS(vrc)) + { + if (fPkcs7) + vrc = doAddPkcs7Signature(pCertificate, hPrivateKey, enmPkcs7DigestType, + cIntermediateCerts, papszIntermediateCerts, hVfsFileManifest, + iVerbosity, pErrInfo, hVfsFileSignature); + if (RT_SUCCESS(vrc)) + { + /* + * Success. + */ + *phVfsFileSignature = hVfsFileSignature; + hVfsFileSignature = NIL_RTVFSFILE; + } + } + else + RTMsgError(Appliance::tr("Failed to write certificate to signature file: %Rrc%#RTeim"), + vrc, &pErrInfo->Core); + } + else + RTMsgError(Appliance::tr("Failed to produce signature file: %Rrc"), vrc); + RTVfsFileRelease(hVfsFileSignature); + } + else + RTMsgError(Appliance::tr("RTVfsMemFileCreate failed: %Rrc"), vrc); + } + else + RTMsgError(Appliance::tr("Encountered a problem when validating the signature we just created: %Rrc%#RTeim\n" + "Please make sure the certificate and private key matches."), + vrc, &pErrInfo->Core); + } + else + RTMsgError(Appliance::tr("2nd RTCrPkixPubKeySignDigest call failed: %Rrc%#RTeim"), vrc, pErrInfo->Core); + RTMemFree(pvSignature); + } + else + vrc = RTMsgErrorRc(VERR_NO_MEMORY, Appliance::tr("Out of memory!")); + } + else + RTMsgError(Appliance::tr("RTCrPkixPubKeySignDigest failed: %Rrc%#RTeim"), vrc, pErrInfo->Core); + } + else + RTMsgError(Appliance::tr("Failed to create digest %s: %Rrc"), RTCrDigestTypeToName(enmDigestType), vrc); + RTCrDigestRelease(hDigest); + return vrc; +} + + +/** + * Handles the 'ovasign' command. + */ +RTEXITCODE handleSignAppliance(HandlerArg *arg) +{ + /* + * Parse arguments. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--certificate", 'c', RTGETOPT_REQ_STRING }, + { "--private-key", 'k', RTGETOPT_REQ_STRING }, + { "--private-key-password", 'p', RTGETOPT_REQ_STRING }, + { "--private-key-password-file",'P', RTGETOPT_REQ_STRING }, + { "--digest-type", 'd', RTGETOPT_REQ_STRING }, + { "--pkcs7", '7', RTGETOPT_REQ_NOTHING }, + { "--cms", '7', RTGETOPT_REQ_NOTHING }, + { "--no-pkcs7", 'n', RTGETOPT_REQ_NOTHING }, + { "--no-cms", 'n', RTGETOPT_REQ_NOTHING }, + { "--intermediate-cert-file", 'i', RTGETOPT_REQ_STRING }, + { "--force", 'f', RTGETOPT_REQ_NOTHING }, + { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, + { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, + { "--dry-run", 'D', RTGETOPT_REQ_NOTHING }, + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, arg->argc, arg->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + const char *pszOva = NULL; + const char *pszCertificate = NULL; + const char *pszPrivateKey = NULL; + Utf8Str strPrivateKeyPassword; + RTDIGESTTYPE enmDigestType = RTDIGESTTYPE_UNKNOWN; + bool fPkcs7 = true; + unsigned cIntermediateCerts = 0; + const char *apszIntermediateCerts[32]; + bool fReSign = false; + unsigned iVerbosity = 1; + bool fDryRun = false; + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'c': + pszCertificate = ValueUnion.psz; + break; + + case 'k': + pszPrivateKey = ValueUnion.psz; + break; + + case 'p': + if (strPrivateKeyPassword.isNotEmpty()) + RTMsgWarning(Appliance::tr("Password is given more than once.")); + strPrivateKeyPassword = ValueUnion.psz; + break; + + case 'P': + { + if (strPrivateKeyPassword.isNotEmpty()) + RTMsgWarning(Appliance::tr("Password is given more than once.")); + RTEXITCODE rcExit = readPasswordFile(ValueUnion.psz, &strPrivateKeyPassword); + if (rcExit == RTEXITCODE_SUCCESS) + break; + return rcExit; + } + + case 'd': + if ( RTStrICmp(ValueUnion.psz, "sha1") == 0 + || RTStrICmp(ValueUnion.psz, "sha-1") == 0) + enmDigestType = RTDIGESTTYPE_SHA1; + else if ( RTStrICmp(ValueUnion.psz, "sha256") == 0 + || RTStrICmp(ValueUnion.psz, "sha-256") == 0) + enmDigestType = RTDIGESTTYPE_SHA256; + else if ( RTStrICmp(ValueUnion.psz, "sha512") == 0 + || RTStrICmp(ValueUnion.psz, "sha-512") == 0) + enmDigestType = RTDIGESTTYPE_SHA512; + else + return RTMsgErrorExitFailure(Appliance::tr("Unknown digest type: %s"), ValueUnion.psz); + break; + + case '7': + fPkcs7 = true; + break; + + case 'n': + fPkcs7 = false; + break; + + case 'i': + if (cIntermediateCerts >= RT_ELEMENTS(apszIntermediateCerts)) + return RTMsgErrorExitFailure(Appliance::tr("Too many intermediate certificates: max %zu"), + RT_ELEMENTS(apszIntermediateCerts)); + apszIntermediateCerts[cIntermediateCerts++] = ValueUnion.psz; + fPkcs7 = true; + break; + + case 'f': + fReSign = true; + break; + + case 'v': + iVerbosity++; + break; + + case 'q': + iVerbosity = 0; + break; + + case 'D': + fDryRun = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszOva) + { + pszOva = ValueUnion.psz; + break; + } + RT_FALL_THRU(); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Required paramaters: */ + if (!pszOva || !*pszOva) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Appliance::tr("No OVA file was specified!")); + if (!pszCertificate || !*pszCertificate) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Appliance::tr("No signing certificate (--certificate=<file>) was specified!")); + if (!pszPrivateKey || !*pszPrivateKey) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, Appliance::tr("No signing private key (--private-key=<file>) was specified!")); + + /* Check that input files exists before we commence: */ + if (!RTFileExists(pszOva)) + return RTMsgErrorExitFailure(Appliance::tr("The specified OVA file was not found: %s"), pszOva); + if (!RTFileExists(pszCertificate)) + return RTMsgErrorExitFailure(Appliance::tr("The specified certificate file was not found: %s"), pszCertificate); + if (!RTFileExists(pszPrivateKey)) + return RTMsgErrorExitFailure(Appliance::tr("The specified private key file was not found: %s"), pszPrivateKey); + + /* + * Open the OVA, read the manifest and look for any existing signature. + */ + RTVFSFSSTREAM hVfsFssOva = NIL_RTVFSFSSTREAM; + RTVFSOBJ hVfsOldSignature = NIL_RTVFSOBJ; + RTVFSFILE hVfsFileManifest = NIL_RTVFSFILE; + Utf8Str strManifestName; + vrc = openOvaAndGetManifestAndOldSignature(pszOva, iVerbosity, fReSign, + &hVfsFssOva, &strManifestName, &hVfsFileManifest, &hVfsOldSignature); + if (RT_SUCCESS(vrc)) + { + /* + * Read the certificate and private key. + */ + RTERRINFOSTATIC ErrInfo; + RTCRX509CERTIFICATE Certificate; + vrc = RTCrX509Certificate_ReadFromFile(&Certificate, pszCertificate, 0, &g_RTAsn1DefaultAllocator, + RTErrInfoInitStatic(&ErrInfo)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Appliance::tr("Error reading certificate from '%s': %Rrc%#RTeim"), + pszCertificate, vrc, &ErrInfo.Core); + + RTCRKEY hPrivateKey = NIL_RTCRKEY; + vrc = RTCrKeyCreateFromFile(&hPrivateKey, 0 /*fFlags*/, pszPrivateKey, strPrivateKeyPassword.c_str(), + RTErrInfoInitStatic(&ErrInfo)); + if (RT_SUCCESS(vrc)) + { + if (iVerbosity > 1) + RTMsgInfo(Appliance::tr("Successfully read the certificate and private key.")); + + /* + * Do the signing and create the signature file. + */ + RTVFSFILE hVfsFileSignature = NIL_RTVFSFILE; + vrc = doTheOvaSigning(&Certificate, hPrivateKey, enmDigestType, strManifestName.c_str(), hVfsFileManifest, + fPkcs7, cIntermediateCerts, apszIntermediateCerts, iVerbosity, &ErrInfo, &hVfsFileSignature); + + /* + * Construct the signature filename: + */ + if (RT_SUCCESS(vrc)) + { + Utf8Str strSignatureName; + vrc = strSignatureName.assignNoThrow(strManifestName); + if (RT_SUCCESS(vrc)) + vrc = strSignatureName.stripSuffix().appendNoThrow(".cert"); + if (RT_SUCCESS(vrc) && !fDryRun) + { + /* + * Update the OVA. + */ + vrc = updateTheOvaSignature(hVfsFssOva, pszOva, strSignatureName.c_str(), + hVfsFileSignature, hVfsOldSignature, iVerbosity); + if (RT_SUCCESS(vrc) && iVerbosity > 0) + RTMsgInfo(Appliance::tr("Successfully signed '%s'."), pszOva); + } + } + RTCrKeyRelease(hPrivateKey); + } + else + RTPrintf(Appliance::tr("Error reading the private key from %s: %Rrc%#RTeim"), pszPrivateKey, vrc, &ErrInfo.Core); + RTCrX509Certificate_Delete(&Certificate); + } + + RTVfsObjRelease(hVfsOldSignature); + RTVfsFileRelease(hVfsFileManifest); + RTVfsFsStrmRelease(hVfsFssOva); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp new file mode 100644 index 00000000..910f5ad5 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageBandwidthControl.cpp @@ -0,0 +1,384 @@ +/* $Id: VBoxManageBandwidthControl.cpp $ */ +/** @file + * VBoxManage - The bandwidth control related commands. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/err.h> +#include <iprt/path.h> +#include <iprt/param.h> +#include <iprt/string.h> +#include <iprt/ctype.h> +#include <iprt/stream.h> +#include <iprt/getopt.h> +#include <VBox/log.h> + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(BWControl); + +// funcs +/////////////////////////////////////////////////////////////////////////////// + + +/** + * Parses a string in the following format "n[k|m|g|K|M|G]". Stores the value + * of n expressed in bytes to *pLimit. k meas kilobit, while K means kilobyte. + * + * @returns Error message or NULL if successful. + * @param pcszLimit The string to parse. + * @param pLimit Where to store the result. + */ +static const char *parseLimit(const char *pcszLimit, int64_t *pLimit) +{ + int iMultiplier = _1M; + char *pszNext = NULL; + int vrc = RTStrToInt64Ex(pcszLimit, &pszNext, 10, pLimit); + + switch (vrc) + { + case VINF_SUCCESS: + break; + case VWRN_NUMBER_TOO_BIG: + return BWControl::tr("Limit is too big\n"); + case VWRN_TRAILING_CHARS: + switch (*pszNext) + { + case 'G': iMultiplier = _1G; break; + case 'M': iMultiplier = _1M; break; + case 'K': iMultiplier = _1K; break; + case 'g': iMultiplier = 125000000; break; + case 'm': iMultiplier = 125000; break; + case 'k': iMultiplier = 125; break; + default: return BWControl::tr("Invalid unit suffix. Valid suffixes are: k, m, g, K, M, G\n"); + } + break; + case VWRN_TRAILING_SPACES: + return BWControl::tr("Trailing spaces in limit!\n"); + case VERR_NO_DIGITS: + return BWControl::tr("No digits in limit specifier\n"); + default: + return BWControl::tr("Invalid limit specifier\n"); + } + if (*pLimit < 0) + return BWControl::tr("Limit cannot be negative\n"); + if (*pLimit > INT64_MAX / iMultiplier) + return BWControl::tr("Limit is too big\n"); + *pLimit *= iMultiplier; + + return NULL; +} + +/** + * Handles the 'bandwidthctl myvm add' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param bwCtrl Reference to the bandwidth control interface. + */ +static RTEXITCODE handleBandwidthControlAdd(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl) +{ + HRESULT hrc = S_OK; + static const RTGETOPTDEF g_aBWCtlAddOptions[] = + { + { "--type", 't', RTGETOPT_REQ_STRING }, + { "--limit", 'l', RTGETOPT_REQ_STRING } + }; + + setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_ADD); + + Bstr name(a->argv[2]); + if (name.isEmpty()) + { + errorArgument(BWControl::tr("Bandwidth group name must not be empty!\n")); + return RTEXITCODE_FAILURE; + } + + const char *pszType = NULL; + int64_t cMaxBytesPerSec = INT64_MAX; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, g_aBWCtlAddOptions, + RT_ELEMENTS(g_aBWCtlAddOptions), 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + + while ( SUCCEEDED(hrc) + && (c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 't': // bandwidth group type + { + if (ValueUnion.psz) + pszType = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'l': // limit + { + if (ValueUnion.psz) + { + const char *pcszError = parseLimit(ValueUnion.psz, &cMaxBytesPerSec); + if (pcszError) + { + errorArgument(pcszError); + return RTEXITCODE_FAILURE; + } + } + else + hrc = E_FAIL; + break; + } + + default: + { + errorGetOpt(c, &ValueUnion); + hrc = E_FAIL; + break; + } + } + } + + BandwidthGroupType_T enmType; + + if (!RTStrICmp(pszType, "disk")) + enmType = BandwidthGroupType_Disk; + else if (!RTStrICmp(pszType, "network")) + enmType = BandwidthGroupType_Network; + else + { + errorArgument(BWControl::tr("Invalid bandwidth group type\n")); + return RTEXITCODE_FAILURE; + } + + CHECK_ERROR2I_RET(bwCtrl, CreateBandwidthGroup(name.raw(), enmType, (LONG64)cMaxBytesPerSec), RTEXITCODE_FAILURE); + + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the 'bandwidthctl myvm set' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param bwCtrl Reference to the bandwidth control interface. + */ +static RTEXITCODE handleBandwidthControlSet(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl) +{ + HRESULT hrc = S_OK; + static const RTGETOPTDEF g_aBWCtlAddOptions[] = + { + { "--limit", 'l', RTGETOPT_REQ_STRING } + }; + + setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_SET); + + Bstr name(a->argv[2]); + int64_t cMaxBytesPerSec = INT64_MAX; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, g_aBWCtlAddOptions, + RT_ELEMENTS(g_aBWCtlAddOptions), 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + + while ( SUCCEEDED(hrc) + && (c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'l': // limit + { + if (ValueUnion.psz) + { + const char *pcszError = parseLimit(ValueUnion.psz, &cMaxBytesPerSec); + if (pcszError) + { + errorArgument(pcszError); + return RTEXITCODE_FAILURE; + } + } + else + hrc = E_FAIL; + break; + } + + default: + { + errorGetOpt(c, &ValueUnion); + hrc = E_FAIL; + break; + } + } + } + + + if (cMaxBytesPerSec != INT64_MAX) + { + ComPtr<IBandwidthGroup> bwGroup; + CHECK_ERROR2I_RET(bwCtrl, GetBandwidthGroup(name.raw(), bwGroup.asOutParam()), RTEXITCODE_FAILURE); + if (SUCCEEDED(hrc)) + { + CHECK_ERROR2I_RET(bwGroup, COMSETTER(MaxBytesPerSec)((LONG64)cMaxBytesPerSec), RTEXITCODE_FAILURE); + } + } + + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the 'bandwidthctl myvm remove' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param bwCtrl Reference to the bandwidth control interface. + */ +static RTEXITCODE handleBandwidthControlRemove(HandlerArg *a, ComPtr<IBandwidthControl> &bwCtrl) +{ + setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_REMOVE); + + Bstr name(a->argv[2]); + CHECK_ERROR2I_RET(bwCtrl, DeleteBandwidthGroup(name.raw()), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the 'bandwidthctl myvm list' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param bwCtrl Reference to the bandwidth control interface. + */ +static RTEXITCODE handleBandwidthControlList(HandlerArg *pArgs, ComPtr<IBandwidthControl> &rptrBWControl) +{ + static const RTGETOPTDEF g_aOptions[] = + { + { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING }, + }; + + setCurrentSubcommand(HELP_SCOPE_BANDWIDTHCTL_LIST); + VMINFO_DETAILS enmDetails = VMINFO_STANDARD; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, g_aOptions, RT_ELEMENTS(g_aOptions), 2 /*iArg*/, 0 /*fFlags*/); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'M': + enmDetails = VMINFO_MACHINEREADABLE; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (FAILED(showBandwidthGroups(rptrBWControl, enmDetails))) + return RTEXITCODE_FAILURE; + + return RTEXITCODE_SUCCESS; +} + + +/** + * Handles the 'bandwidthctl' command. + * @returns Exit code. + * @param a The handler argument package. + */ +RTEXITCODE handleBandwidthControl(HandlerArg *a) +{ + HRESULT hrc = S_OK; + ComPtr<IMachine> machine; + ComPtr<IBandwidthControl> bwCtrl; + + if (a->argc < 2) + return errorSyntax(BWControl::tr("Too few parameters")); + else if (a->argc > 7) + return errorSyntax(BWControl::tr("Too many parameters")); + + /* try to find the given machine */ + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + + /* open a session for the VM (new or shared) */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + SessionType_T st; + CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), RTEXITCODE_FAILURE); + bool fRunTime = (st == SessionType_Shared); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + hrc = machine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam()); + if (FAILED(hrc)) goto leave; /** @todo r=andy Argh!! */ + + if (!strcmp(a->argv[1], "add")) + { + if (fRunTime) + { + errorArgument(BWControl::tr("Bandwidth groups cannot be created while the VM is running\n")); + goto leave; + } + hrc = handleBandwidthControlAdd(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "remove")) + { + if (fRunTime) + { + errorArgument(BWControl::tr("Bandwidth groups cannot be deleted while the VM is running\n")); + goto leave; + } + hrc = handleBandwidthControlRemove(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "set")) + hrc = handleBandwidthControlSet(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + else if (!strcmp(a->argv[1], "list")) + hrc = handleBandwidthControlList(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + else + { + errorSyntax(BWControl::tr("Invalid parameter '%s'"), a->argv[1]); + hrc = E_FAIL; + } + + /* commit changes */ + if (SUCCEEDED(hrc)) + CHECK_ERROR(machine, SaveSettings()); + +leave: + /* it's important to always close sessions */ + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageCloud.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageCloud.cpp new file mode 100644 index 00000000..690cb7d9 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageCloud.cpp @@ -0,0 +1,2654 @@ +/* $Id: VBoxManageCloud.cpp $ */ +/** @file + * VBoxManageCloud - The cloud related commands. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/ctype.h> +#include <iprt/getopt.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/thread.h> +#include <iprt/uuid.h> +#include <iprt/file.h> +#include <iprt/http.h> +#include <VBox/log.h> + +#include <iprt/cpp/path.h> + +#include "VBoxManage.h" + +#include <list> + +using namespace com;//at least for Bstr + +DECLARE_TRANSLATION_CONTEXT(Cloud); + + +/** + * Common Cloud options. + */ +typedef struct +{ + struct { + const char *pszProviderName; + ComPtr<ICloudProvider> pCloudProvider; + }provider; + struct { + const char *pszProfileName; + ComPtr<ICloudProfile> pCloudProfile; + }profile; + +} CLOUDCOMMONOPT; +typedef CLOUDCOMMONOPT *PCLOUDCOMMONOPT; + +static HRESULT checkAndSetCommonOptions(HandlerArg *a, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + Bstr bstrProvider(pCommonOpts->provider.pszProviderName); + Bstr bstrProfile(pCommonOpts->profile.pszProfileName); + + /* check for required options */ + if (bstrProvider.isEmpty()) + { + errorSyntax(Cloud::tr("Parameter --provider is required")); + return E_FAIL; + } + if (bstrProfile.isEmpty()) + { + errorSyntax(Cloud::tr("Parameter --profile is required")); + return E_FAIL; + } + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + pCommonOpts->provider.pCloudProvider = pCloudProvider; + + ComPtr<ICloudProfile> pCloudProfile; + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(bstrProfile.raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + pCommonOpts->profile.pCloudProfile = pCloudProfile; + + return hrc; +} + + +/** + * List all available cloud instances for the specified cloud provider. + * Available cloud instance is one which state whether "running" or "stopped". + * + * @returns RTEXITCODE + * @param a is the list of passed arguments + * @param iFirst is the position of the first unparsed argument in the arguments list + * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common + * arguments which have been already parsed before + */ +static RTEXITCODE listCloudInstances(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + static const RTGETOPTDEF s_aOptions[] = + { + { "--compartment-id", 'c', RTGETOPT_REQ_STRING }, + { "--state", 's', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + Utf8Str strCompartmentId; + com::SafeArray<CloudMachineState_T> machineStates; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'c': + strCompartmentId = ValueUnion.psz; + break; + + case 's': + { + const char * const pszState = ValueUnion.psz; + + if (RTStrICmp(pszState, "creatingimage") == 0) + machineStates.push_back(CloudMachineState_CreatingImage); + else if (RTStrICmp(pszState, "paused") == 0) /* XXX */ + machineStates.push_back(CloudMachineState_Stopped); + else if (RTStrICmp(pszState, "provisioning") == 0) + machineStates.push_back(CloudMachineState_Provisioning); + else if (RTStrICmp(pszState, "running") == 0) + machineStates.push_back(CloudMachineState_Running); + else if (RTStrICmp(pszState, "starting") == 0) + machineStates.push_back(CloudMachineState_Starting); + else if (RTStrICmp(pszState, "stopped") == 0) + machineStates.push_back(CloudMachineState_Stopped); + else if (RTStrICmp(pszState, "stopping") == 0) + machineStates.push_back(CloudMachineState_Stopping); + else if (RTStrICmp(pszState, "terminated") == 0) + machineStates.push_back(CloudMachineState_Terminated); + else if (RTStrICmp(pszState, "terminating") == 0) + machineStates.push_back(CloudMachineState_Terminating); + else + return errorArgument(Cloud::tr("Unknown cloud instance state \"%s\""), pszState); + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + HRESULT hrc = S_OK; + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProfile> pCloudProfile; + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + + if (strCompartmentId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, pCloudProfile, + SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()), + RTEXITCODE_FAILURE); + } + else + { + RTPrintf(Cloud::tr("Parameter \'compartment\' is empty or absent.\n" + "Trying to get the compartment from the passed cloud profile \'%s\'\n"), + pCommonOpts->profile.pszProfileName); + Bstr bStrCompartmentId; + CHECK_ERROR2_RET(hrc, pCloudProfile, + GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()), + RTEXITCODE_FAILURE); + strCompartmentId = bStrCompartmentId; + if (strCompartmentId.isNotEmpty()) + RTPrintf(Cloud::tr("Found the compartment \'%s\':\n"), strCompartmentId.c_str()); + else + return errorSyntax(Cloud::tr("Parameter --compartment-id is required")); + } + + Bstr bstrProfileName; + pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam()); + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<IStringArray> pVMNamesHolder; + ComPtr<IStringArray> pVMIdsHolder; + com::SafeArray<BSTR> arrayVMNames; + com::SafeArray<BSTR> arrayVMIds; + ComPtr<IProgress> pProgress; + + RTPrintf(Cloud::tr("Reply is in the form \'instance name\' = \'instance id\'\n")); + + CHECK_ERROR2_RET(hrc, oCloudClient, + ListInstances(ComSafeArrayAsInParam(machineStates), + pVMNamesHolder.asOutParam(), + pVMIdsHolder.asOutParam(), + pProgress.asOutParam()), + RTEXITCODE_FAILURE); + showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Failed to list instances")), RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, + pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)), + RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, + pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)), + RTEXITCODE_FAILURE); + + RTPrintf(Cloud::tr("The list of the instances for the cloud profile \'%ls\'\nand compartment \'%s\':\n"), + bstrProfileName.raw(), strCompartmentId.c_str()); + size_t cIds = arrayVMIds.size(); + size_t cNames = arrayVMNames.size(); + for (size_t k = 0; k < cNames; k++) + { + Bstr value; + if (k < cIds) + value = arrayVMIds[k]; + RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/** + * List all available cloud images for the specified cloud provider. + * + * @returns RTEXITCODE + * @param a is the list of passed arguments + * @param iFirst is the position of the first unparsed argument in the arguments list + * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common + * arguments which have been already parsed before + */ +static RTEXITCODE listCloudImages(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + static const RTGETOPTDEF s_aOptions[] = + { + { "--compartment-id", 'c', RTGETOPT_REQ_STRING }, + { "--state", 's', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + Utf8Str strCompartmentId; + com::SafeArray<CloudImageState_T> imageStates; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'c': + strCompartmentId = ValueUnion.psz; + break; + + case 's': + { + const char * const pszState = ValueUnion.psz; + + if (RTStrICmp(pszState, "available") == 0) + imageStates.push_back(CloudImageState_Available); + else if (RTStrICmp(pszState, "deleted") == 0) + imageStates.push_back(CloudImageState_Deleted); + else if (RTStrICmp(pszState, "disabled") == 0) + imageStates.push_back(CloudImageState_Disabled); + else if (RTStrICmp(pszState, "exporting") == 0) + imageStates.push_back(CloudImageState_Exporting); + else if (RTStrICmp(pszState, "importing") == 0) + imageStates.push_back(CloudImageState_Importing); + else if (RTStrICmp(pszState, "provisioning") == 0) + imageStates.push_back(CloudImageState_Provisioning); + else + return errorArgument(Cloud::tr("Unknown cloud image state \"%s\""), pszState); + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + + HRESULT hrc = S_OK; + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProfile> pCloudProfile; + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + + if (strCompartmentId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, pCloudProfile, + SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),\ + RTEXITCODE_FAILURE); + } + else + { + RTPrintf(Cloud::tr("Parameter \'compartment\' is empty or absent.\n" + "Trying to get the compartment from the passed cloud profile \'%s\'\n"), + pCommonOpts->profile.pszProfileName); + Bstr bStrCompartmentId; + CHECK_ERROR2_RET(hrc, pCloudProfile, + GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()), + RTEXITCODE_FAILURE); + strCompartmentId = bStrCompartmentId; + if (strCompartmentId.isNotEmpty()) + RTPrintf(Cloud::tr("Found the compartment \'%s\':\n"), strCompartmentId.c_str()); + else + return errorSyntax(Cloud::tr("Parameter --compartment-id is required")); + } + + Bstr bstrProfileName; + pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam()); + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<IStringArray> pVMNamesHolder; + ComPtr<IStringArray> pVMIdsHolder; + com::SafeArray<BSTR> arrayVMNames; + com::SafeArray<BSTR> arrayVMIds; + ComPtr<IProgress> pProgress; + + RTPrintf(Cloud::tr("Reply is in the form \'image name\' = \'image id\'\n")); + CHECK_ERROR2_RET(hrc, oCloudClient, + ListImages(ComSafeArrayAsInParam(imageStates), + pVMNamesHolder.asOutParam(), + pVMIdsHolder.asOutParam(), + pProgress.asOutParam()), + RTEXITCODE_FAILURE); + showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Failed to list images")), RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, + pVMNamesHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMNames)), + RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, + pVMIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVMIds)), + RTEXITCODE_FAILURE); + + RTPrintf(Cloud::tr("The list of the images for the cloud profile \'%ls\'\nand compartment \'%s\':\n"), + bstrProfileName.raw(), strCompartmentId.c_str()); + size_t cNames = arrayVMNames.size(); + size_t cIds = arrayVMIds.size(); + for (size_t k = 0; k < cNames; k++) + { + Bstr value; + if (k < cIds) + value = arrayVMIds[k]; + RTPrintf("\t%ls = %ls\n", arrayVMNames[k], value.raw()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/** + * List all available cloud vnic attachments for the specified cloud provider. + * + * @returns RTEXITCODE + * @param a is the list of passed arguments + * @param iFirst is the position of the first unparsed argument in the arguments list + * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common + * arguments which have been already parsed before + */ +static RTEXITCODE listCloudVnicAttachments(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + static const RTGETOPTDEF s_aOptions[] = + { + { "--compartment-id", 'c', RTGETOPT_REQ_STRING }, + { "--filter", 'f', RTGETOPT_REQ_STRING },/*instanceId=<id>, vnicId=<id>, domainName=<name>*/ + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + com::SafeArray<BSTR> parameters; + Utf8Str strCompartmentId; + Utf8Str filterList; + HRESULT hrc = S_OK; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'c': + strCompartmentId = ValueUnion.psz; + Bstr(Utf8Str("compartmentId=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + + case 'f': + filterList.append(ValueUnion.psz).append(","); + Bstr(Utf8Str(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + RTPrintf(Cloud::tr("Filters: \'%s\' \n"), filterList.c_str()); + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(Bstr(pCommonOpts->provider.pszProviderName).raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProfile> pCloudProfile; + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(Bstr(pCommonOpts->profile.pszProfileName).raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + + if (strCompartmentId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, pCloudProfile, + SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()),\ + RTEXITCODE_FAILURE); + } + else + { + RTPrintf(Cloud::tr("Parameter \'compartment\' is empty or absent.\n" + "Trying to get the compartment from the passed cloud profile \'%s\'\n"), pCommonOpts->profile.pszProfileName); + Bstr bStrCompartmentId; + CHECK_ERROR2_RET(hrc, pCloudProfile, + GetProperty(Bstr("compartment").raw(), bStrCompartmentId.asOutParam()), + RTEXITCODE_FAILURE); + strCompartmentId = bStrCompartmentId; + if (strCompartmentId.isNotEmpty()) + RTPrintf(Cloud::tr("Found the compartment \'%s\':\n"), strCompartmentId.c_str()); + else + return errorArgument(Cloud::tr("Parameter --compartment-id is required.")); + } + + Bstr bstrProfileName; + pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam()); + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<IStringArray> pVnicAttachmentIdsHolder; + ComPtr<IStringArray> pVnicIdsHolder; + com::SafeArray<BSTR> arrayVnicAttachmentIds; + com::SafeArray<BSTR> arrayVnicIds; + ComPtr<IProgress> pProgress; + + RTPrintf(Cloud::tr("Reply is in the form \'Vnic attachment <id>\': \n\t \'Vnic <id>\'\n")); + CHECK_ERROR2_RET(hrc, oCloudClient, + ListVnicAttachments(ComSafeArrayAsInParam(parameters), + pVnicAttachmentIdsHolder.asOutParam(), + pVnicIdsHolder.asOutParam(), + pProgress.asOutParam()), + RTEXITCODE_FAILURE); + showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Failed to list Vnic attachments")), RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, + pVnicAttachmentIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVnicAttachmentIds)), + RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, + pVnicIdsHolder, COMGETTER(Values)(ComSafeArrayAsOutParam(arrayVnicIds)), + RTEXITCODE_FAILURE); + + RTPrintf(Cloud::tr("The list of the Vnic attachments:\n")); + size_t cVnicAttchIds = arrayVnicAttachmentIds.size(); + size_t cVnicIds = arrayVnicIds.size(); + + if (cVnicAttchIds == 0) + RTPrintf(Cloud::tr("\tEmpty\n")); + else + { + Bstr value; + for (size_t k = 0; k < cVnicAttchIds; k++) + { + if (k < cVnicIds) + value = arrayVnicIds[k]; + RTPrintf(Cloud::tr("Vnic attachment id [%ls]:\n\t Vnic id - %ls\n"), arrayVnicAttachmentIds[k], value.raw()); + } + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/** + * General function which handles the "list" commands + * + * @returns RTEXITCODE + * @param a is the list of passed arguments + * @param iFirst is the position of the first unparsed argument in the arguments list + * @param pCommonOpts is a pointer to the structure CLOUDCOMMONOPT with some common + * arguments which have been already parsed before + */ +static RTEXITCODE handleCloudLists(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + enum + { + kCloudListIota = 1000, + kCloudList_Images, + kCloudList_Instances, + kCloudList_Machines, + kCloudList_Networks, + kCloudList_Objects, + kCloudList_Subnets, + kCloudList_Vcns, + kCloudList_VnicAttachments, + }; + + static const RTGETOPTDEF s_aOptions[] = + { + { "images", kCloudList_Images, RTGETOPT_REQ_NOTHING }, + { "instances", kCloudList_Instances, RTGETOPT_REQ_NOTHING }, + { "machines", kCloudList_Machines, RTGETOPT_REQ_NOTHING }, + { "networks", kCloudList_Networks, RTGETOPT_REQ_NOTHING }, + { "objects", kCloudList_Objects, RTGETOPT_REQ_NOTHING }, + { "subnets", kCloudList_Subnets, RTGETOPT_REQ_NOTHING }, + { "vcns", kCloudList_Vcns, RTGETOPT_REQ_NOTHING }, + { "vms", kCloudList_Machines, RTGETOPT_REQ_NOTHING }, + { "vnicattachments", kCloudList_VnicAttachments, RTGETOPT_REQ_NOTHING }, + + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "-?", 'h', RTGETOPT_REQ_NOTHING }, + { "-help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING }, + }; + + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case kCloudList_Images: + setCurrentSubcommand(HELP_SCOPE_CLOUDLIST_IMAGES); + return listCloudImages(a, GetState.iNext, pCommonOpts); + + case kCloudList_Instances: + setCurrentSubcommand(HELP_SCOPE_CLOUDLIST_INSTANCES); + return listCloudInstances(a, GetState.iNext, pCommonOpts); + case kCloudList_Machines: + return listCloudMachines(a, GetState.iNext, + pCommonOpts->provider.pszProviderName, + pCommonOpts->profile.pszProfileName); + + case kCloudList_VnicAttachments: + setCurrentSubcommand(HELP_SCOPE_CLOUDLIST_VNICATTACHMENTS); + return listCloudVnicAttachments(a, GetState.iNext, pCommonOpts); + + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + return errorNoSubcommand(); +} + + +static RTEXITCODE createCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + enum + { + kInstanceIota = 1000, + kInstance_ShapeCpu, + kInstance_ShapeMemory, + }; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--image-id", 'i', RTGETOPT_REQ_STRING }, + { "--boot-volume-id", 'v', RTGETOPT_REQ_STRING }, + { "--display-name", 'n', RTGETOPT_REQ_STRING }, + { "--launch-mode", 'm', RTGETOPT_REQ_STRING }, + { "--shape", 's', RTGETOPT_REQ_STRING }, + { "--shape-cpus", kInstance_ShapeCpu, RTGETOPT_REQ_UINT32 }, + { "--shape-memory", kInstance_ShapeMemory, RTGETOPT_REQ_UINT32 }, + { "--domain-name", 'd', RTGETOPT_REQ_STRING }, + { "--boot-disk-size", 'b', RTGETOPT_REQ_STRING }, + { "--publicip", 'p', RTGETOPT_REQ_STRING }, + { "--subnet", 't', RTGETOPT_REQ_STRING }, + { "--privateip", 'P', RTGETOPT_REQ_STRING }, + { "--launch", 'l', RTGETOPT_REQ_STRING }, + { "--public-ssh-key", 'k', RTGETOPT_REQ_STRING }, + { "--cloud-init-script-path", 'c', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + ComPtr<IAppliance> pAppliance; + CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE); + ULONG vsdNum = 1; + CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(1, &vsdNum), RTEXITCODE_FAILURE); + com::SafeIfaceArray<IVirtualSystemDescription> virtualSystemDescriptions; + CHECK_ERROR2_RET(hrc, pAppliance, + COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(virtualSystemDescriptions)), + RTEXITCODE_FAILURE); + ComPtr<IVirtualSystemDescription> pVSD = virtualSystemDescriptions[0]; + + Utf8Str strDisplayName, strImageId, strBootVolumeId, strPublicSSHKey; + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + strImageId = ValueUnion.psz; + pVSD->AddDescription(VirtualSystemDescriptionType_CloudImageId, + Bstr(ValueUnion.psz).raw(), NULL); + break; + + case 'v': + strBootVolumeId = ValueUnion.psz; + pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootVolumeId, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'n': + strDisplayName = ValueUnion.psz; + pVSD->AddDescription(VirtualSystemDescriptionType_Name, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'm': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCILaunchMode, + Bstr(ValueUnion.psz).raw(), NULL); + break; + + case 's': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudInstanceShape, + Bstr(ValueUnion.psz).raw(), NULL); + break; + + case kInstance_ShapeCpu: + pVSD->AddDescription(VirtualSystemDescriptionType_CloudShapeCpus, + BstrFmt("%RI32", ValueUnion.u32).raw(), NULL); + break; + + case kInstance_ShapeMemory: + pVSD->AddDescription(VirtualSystemDescriptionType_CloudShapeMemory, + BstrFmt("%RI32", ValueUnion.u32).raw(), NULL); + break; + + case 'd': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudDomain, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'b': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudBootDiskSize, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'p': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicIP, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'P': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudPrivateIP, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 't': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudOCISubnet, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'l': + { + Utf8Str strLaunch(ValueUnion.psz); + if (strLaunch.isNotEmpty() && (strLaunch.equalsIgnoreCase("true") || strLaunch.equalsIgnoreCase("false"))) + pVSD->AddDescription(VirtualSystemDescriptionType_CloudLaunchInstance, + Bstr(ValueUnion.psz).raw(), NULL); + break; + } + case 'k': + strPublicSSHKey = ValueUnion.psz; + pVSD->AddDescription(VirtualSystemDescriptionType_CloudPublicSSHKey, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'c': + pVSD->AddDescription(VirtualSystemDescriptionType_CloudInitScriptPath, + Bstr(ValueUnion.psz).raw(), NULL); + break; + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strPublicSSHKey.isEmpty()) + RTPrintf(Cloud::tr("Warning!!! Public SSH key doesn't present in the passed arguments...\n")); + + if (strImageId.isNotEmpty() && strBootVolumeId.isNotEmpty()) + return errorArgument(Cloud::tr("Parameters --image-id and --boot-volume-id are mutually exclusive. " + "Only one of them must be presented.")); + + if (strImageId.isEmpty() && strBootVolumeId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter --image-id or --boot-volume-id. One of them must be presented.")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + pVSD->AddDescription(VirtualSystemDescriptionType_CloudProfileName, + Bstr(pCommonOpts->profile.pszProfileName).raw(), + NULL); + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<IStringArray> infoArray; + com::SafeArray<BSTR> pStrInfoArray; + ComPtr<IProgress> pProgress; + +#if 0 + /* + * OCI API returns an error during an instance creation if the image isn't available + * or in the inappropriate state. So the check can be omitted. + */ + RTPrintf(Cloud::tr("Checking the cloud image with id \'%s\'...\n"), strImageId.c_str()); + CHECK_ERROR2_RET(hrc, oCloudClient, + GetImageInfo(Bstr(strImageId).raw(), + infoArray.asOutParam(), + pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Checking the cloud image failed")), RTEXITCODE_FAILURE); + + pProgress.setNull(); +#endif + + if (strImageId.isNotEmpty()) + RTPrintf(Cloud::tr("Creating cloud instance with name \'%s\' from the image \'%s\'...\n"), + strDisplayName.c_str(), strImageId.c_str()); + else + RTPrintf(Cloud::tr("Creating cloud instance with name \'%s\' from the boot volume \'%s\'...\n"), + strDisplayName.c_str(), strBootVolumeId.c_str()); + + CHECK_ERROR2_RET(hrc, oCloudClient, LaunchVM(pVSD, pProgress.asOutParam()), RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Creating cloud instance failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud instance was created successfully\n")); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE updateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + RT_NOREF(a); + RT_NOREF(iFirst); + RT_NOREF(pCommonOpts); + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE showCloudInstanceInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strInstanceId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + { + if (strInstanceId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strInstanceId = ValueUnion.psz; + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter: --id")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Getting information about cloud instance with id %s...\n"), strInstanceId.c_str()); + RTPrintf(Cloud::tr("Reply is in the form \'setting name\' = \'value\'\n")); + + ComPtr<IAppliance> pAppliance; + CHECK_ERROR2_RET(hrc, a->virtualBox, CreateAppliance(pAppliance.asOutParam()), RTEXITCODE_FAILURE); + + com::SafeIfaceArray<IVirtualSystemDescription> vsdArray; + ULONG requestedVSDnums = 1; + ULONG newVSDnums = 0; + CHECK_ERROR2_RET(hrc, pAppliance, CreateVirtualSystemDescriptions(requestedVSDnums, &newVSDnums), RTEXITCODE_FAILURE); + if (requestedVSDnums != newVSDnums) + return RTEXITCODE_FAILURE; + + CHECK_ERROR2_RET(hrc, pAppliance, COMGETTER(VirtualSystemDescriptions)(ComSafeArrayAsOutParam(vsdArray)), RTEXITCODE_FAILURE); + ComPtr<IVirtualSystemDescription> instanceDescription = vsdArray[0]; + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + GetInstanceInfo(Bstr(strInstanceId).raw(), instanceDescription, progress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Getting information about cloud instance failed")), RTEXITCODE_FAILURE); + + RTPrintf(Cloud::tr("Cloud instance info (provider '%s'):\n"), + pCommonOpts->provider.pszProviderName); + + struct vsdHReadable { + VirtualSystemDescriptionType_T vsdType; + Utf8Str strFound; + Utf8Str strNotFound; + }; + + const size_t vsdHReadableArraySize = 15;//the number of items in the vsdHReadableArray + vsdHReadable vsdHReadableArray[vsdHReadableArraySize] = { + {VirtualSystemDescriptionType_CloudDomain, Cloud::tr("Availability domain = %ls\n"), Cloud::tr("Availability domain wasn't found\n")}, + {VirtualSystemDescriptionType_Name, Cloud::tr("Instance displayed name = %ls\n"), Cloud::tr("Instance displayed name wasn't found\n")}, + {VirtualSystemDescriptionType_CloudInstanceState, Cloud::tr("Instance state = %ls\n"), Cloud::tr("Instance state wasn't found\n")}, + {VirtualSystemDescriptionType_CloudInstanceId, Cloud::tr("Instance Id = %ls\n"), Cloud::tr("Instance Id wasn't found\n")}, + {VirtualSystemDescriptionType_CloudInstanceDisplayName, Cloud::tr("Instance name = %ls\n"), Cloud::tr("Instance name wasn't found\n")}, + {VirtualSystemDescriptionType_CloudImageId, Cloud::tr("Bootable image Id = %ls\n"), + Cloud::tr("Image Id whom the instance is booted up wasn't found\n")}, + {VirtualSystemDescriptionType_CloudInstanceShape, Cloud::tr("Shape of the instance = %ls\n"), + Cloud::tr("The shape of the instance wasn't found\n")}, + {VirtualSystemDescriptionType_OS, Cloud::tr("Type of guest OS = %ls\n"), Cloud::tr("Type of guest OS wasn't found\n")}, + {VirtualSystemDescriptionType_Memory, Cloud::tr("RAM = %ls MB\n"), Cloud::tr("Value for RAM wasn't found\n")}, + {VirtualSystemDescriptionType_CPU, Cloud::tr("CPUs = %ls\n"), Cloud::tr("Numbers of CPUs weren't found\n")}, + {VirtualSystemDescriptionType_CloudPublicIP, Cloud::tr("Instance public IP = %ls\n"), Cloud::tr("Public IP wasn't found\n")}, + {VirtualSystemDescriptionType_Miscellaneous, "%ls\n", Cloud::tr("Miscellanious wasn't found\n")}, + {VirtualSystemDescriptionType_CloudInstanceFreeFormTags, "%ls\n", Cloud::tr("Free-form tags weren't found\n")}, + {VirtualSystemDescriptionType_CloudInstanceMetadata, "%ls\n", Cloud::tr("Metadata was't found\n")}, + {VirtualSystemDescriptionType_CloudInitScriptPath, "Cloud-init script: \n\t%ls\n", Cloud::tr("Cloud-init script wasn't found\n")} + }; + + com::SafeArray<VirtualSystemDescriptionType_T> retTypes; + com::SafeArray<BSTR> aRefs; + com::SafeArray<BSTR> aOvfValues; + com::SafeArray<BSTR> aVBoxValues; + com::SafeArray<BSTR> aExtraConfigValues; + + for (size_t i=0; i<vsdHReadableArraySize ; ++i) + { + hrc = instanceDescription->GetDescriptionByType(vsdHReadableArray[i].vsdType, + ComSafeArrayAsOutParam(retTypes), + ComSafeArrayAsOutParam(aRefs), + ComSafeArrayAsOutParam(aOvfValues), + ComSafeArrayAsOutParam(aVBoxValues), + ComSafeArrayAsOutParam(aExtraConfigValues)); + if (FAILED(hrc) || aVBoxValues.size() == 0) + LogRel((vsdHReadableArray[i].strNotFound.c_str())); + else + { + LogRel(("Size is %d", aVBoxValues.size())); + for (size_t j = 0; j<aVBoxValues.size(); ++j) + { + RTPrintf(vsdHReadableArray[i].strFound.c_str(), aVBoxValues[j]); + } + } + + retTypes.setNull(); + aRefs.setNull(); + aOvfValues.setNull(); + aVBoxValues.setNull(); + aExtraConfigValues.setNull(); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE startCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strInstanceId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + { + if (strInstanceId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strInstanceId = ValueUnion.psz; + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter: --id")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Starting cloud instance with id %s...\n"), strInstanceId.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + StartInstance(Bstr(strInstanceId).raw(), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Starting the cloud instance failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was started\n"), + strInstanceId.c_str(), + pCommonOpts->provider.pszProviderName, + pCommonOpts->profile.pszProfileName); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE pauseCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strInstanceId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + { + if (strInstanceId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strInstanceId = ValueUnion.psz; + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter: --id")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Pausing cloud instance with id %s...\n"), strInstanceId.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + PauseInstance(Bstr(strInstanceId).raw(), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Pause the cloud instance failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was paused\n"), + strInstanceId.c_str(), + pCommonOpts->provider.pszProviderName, + pCommonOpts->profile.pszProfileName); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE terminateCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strInstanceId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + { + if (strInstanceId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strInstanceId = ValueUnion.psz; + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter: --id")); + + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Terminating cloud instance with id %s...\n"), strInstanceId.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + TerminateInstance(Bstr(strInstanceId).raw(), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Termination the cloud instance failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was terminated\n"), + strInstanceId.c_str(), + pCommonOpts->provider.pszProviderName, + pCommonOpts->profile.pszProfileName); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE resetCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strInstanceId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + { + if (strInstanceId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strInstanceId = ValueUnion.psz; + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strInstanceId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter: --id")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Reset cloud instance with id %s...\n"), strInstanceId.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + ResetInstance(Bstr(strInstanceId).raw(), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Reset the cloud instance failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud instance with id %s (provider = '%s', profile = '%s') was reset\n"), + strInstanceId.c_str(), + pCommonOpts->provider.pszProviderName, + pCommonOpts->profile.pszProfileName); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE handleCloudInstance(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + enum + { + kCloudInstanceIota = 1000, + kCloudInstance_Create, + kCloudInstance_Info, + kCloudInstance_Pause, + kCloudInstance_Start, + kCloudInstance_Terminate, + kCloudInstance_Update, + kCloudInstance_Reset, + }; + + static const RTGETOPTDEF s_aOptions[] = + { + { "create", kCloudInstance_Create, RTGETOPT_REQ_NOTHING }, + { "info", kCloudInstance_Info, RTGETOPT_REQ_NOTHING }, + { "pause", kCloudInstance_Pause, RTGETOPT_REQ_NOTHING }, + { "start", kCloudInstance_Start, RTGETOPT_REQ_NOTHING }, + { "terminate", kCloudInstance_Terminate, RTGETOPT_REQ_NOTHING }, + { "update", kCloudInstance_Update, RTGETOPT_REQ_NOTHING }, + { "reset", kCloudInstance_Reset, RTGETOPT_REQ_NOTHING }, + + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "-?", 'h', RTGETOPT_REQ_NOTHING }, + { "-help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING }, + }; + + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + /* Sub-commands: */ + case kCloudInstance_Create: + setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_CREATE); + return createCloudInstance(a, GetState.iNext, pCommonOpts); + + case kCloudInstance_Start: + setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_START); + return startCloudInstance(a, GetState.iNext, pCommonOpts); + + case kCloudInstance_Pause: + setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_PAUSE); + return pauseCloudInstance(a, GetState.iNext, pCommonOpts); + + case kCloudInstance_Info: + setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_INFO); + return showCloudInstanceInfo(a, GetState.iNext, pCommonOpts); + + case kCloudInstance_Update: +// setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_UPDATE); + return updateCloudInstance(a, GetState.iNext, pCommonOpts); + + case kCloudInstance_Terminate: + setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_TERMINATE); + return terminateCloudInstance(a, GetState.iNext, pCommonOpts); + + case kCloudInstance_Reset: + setCurrentSubcommand(HELP_SCOPE_CLOUDINSTANCE_RESET); + return resetCloudInstance(a, GetState.iNext, pCommonOpts); + + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + return errorNoSubcommand(); +} + + +static RTEXITCODE createCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--object-name", 'o', RTGETOPT_REQ_STRING }, + { "--bucket-name", 'b', RTGETOPT_REQ_STRING }, + { "--compartment-id", 'c', RTGETOPT_REQ_STRING }, + { "--instance-id", 'i', RTGETOPT_REQ_STRING }, + { "--display-name", 'd', RTGETOPT_REQ_STRING }, + { "--launch-mode", 'm', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strCompartmentId; + Utf8Str strInstanceId; + Utf8Str strDisplayName; + Utf8Str strBucketName; + Utf8Str strObjectName; + com::SafeArray<BSTR> parameters; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'c': + strCompartmentId=ValueUnion.psz; + Bstr(Utf8Str("compartment-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'i': + strInstanceId=ValueUnion.psz; + Bstr(Utf8Str("instance-id=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'd': + strDisplayName=ValueUnion.psz; + Bstr(Utf8Str("display-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'o': + strObjectName=ValueUnion.psz; + Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'b': + strBucketName=ValueUnion.psz; + Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'm': + strBucketName=ValueUnion.psz; + Bstr(Utf8Str("launch-mode=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strInstanceId.isNotEmpty() && strObjectName.isNotEmpty()) + return errorArgument(Cloud::tr("Conflicting parameters: --instance-id and --object-name can't be used together. Choose one.")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + if (strInstanceId.isNotEmpty()) + RTPrintf(Cloud::tr("Creating cloud image with name \'%s\' from the instance \'%s\'...\n"), + strDisplayName.c_str(), strInstanceId.c_str()); + else + RTPrintf(Cloud::tr("Creating cloud image with name \'%s\' from the object \'%s\' in the bucket \'%s\'...\n"), + strDisplayName.c_str(), strObjectName.c_str(), strBucketName.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + CreateImage(ComSafeArrayAsInParam(parameters), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Creating cloud image failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud image was created successfully\n")); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static RTEXITCODE exportCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "--bucket-name", 'b', RTGETOPT_REQ_STRING }, + { "--object-name", 'o', RTGETOPT_REQ_STRING }, + { "--display-name", 'd', RTGETOPT_REQ_STRING }, + { "--launch-mode", 'm', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strImageId; /* XXX: this is vbox "image", i.e. medium */ + Utf8Str strBucketName; + Utf8Str strObjectName; + Utf8Str strDisplayName; + Utf8Str strLaunchMode; + com::SafeArray<BSTR> parameters; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'b': /* --bucket-name */ + { + if (strBucketName.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --bucket-name")); + + strBucketName = ValueUnion.psz; + if (strBucketName.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --bucket-name")); + + break; + } + + case 'o': /* --object-name */ + { + if (strObjectName.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --object-name")); + + strObjectName = ValueUnion.psz; + if (strObjectName.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --object-name")); + + break; + } + + case 'i': /* --id */ + { + if (strImageId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strImageId = ValueUnion.psz; + if (strImageId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + + case 'd': /* --display-name */ + { + if (strDisplayName.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --display-name")); + + strDisplayName = ValueUnion.psz; + if (strDisplayName.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --display-name")); + + break; + } + + case 'm': /* --launch-mode */ + { + if (strLaunchMode.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --launch-mode")); + + strLaunchMode = ValueUnion.psz; + if (strLaunchMode.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --launch-mode")); + + break; + } + + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strImageId.isNotEmpty()) + BstrFmt("image-id=%s", strImageId.c_str()).detachTo(parameters.appendedRaw()); + else + return errorArgument(Cloud::tr("Missing parameter: --id")); + + if (strBucketName.isNotEmpty()) + BstrFmt("bucket-name=%s", strBucketName.c_str()).detachTo(parameters.appendedRaw()); + else + return errorArgument(Cloud::tr("Missing parameter: --bucket-name")); + + if (strObjectName.isNotEmpty()) + BstrFmt("object-name=%s", strObjectName.c_str()).detachTo(parameters.appendedRaw()); + + if (strDisplayName.isNotEmpty()) + BstrFmt("display-name=%s", strDisplayName.c_str()).detachTo(parameters.appendedRaw()); + + if (strLaunchMode.isNotEmpty()) + BstrFmt("launch-mode=%s", strLaunchMode.c_str()).detachTo(parameters.appendedRaw()); + + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + + if (strObjectName.isNotEmpty()) + RTPrintf(Cloud::tr("Exporting image \'%s\' to the Cloud with name \'%s\'...\n"), + strImageId.c_str(), strObjectName.c_str()); + else + RTPrintf(Cloud::tr("Exporting image \'%s\' to the Cloud with default name\n"), + strImageId.c_str()); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + SafeIfaceArray<IMedium> aImageList; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(HardDisks)(ComSafeArrayAsOutParam(aImageList)), + RTEXITCODE_FAILURE); + + ComPtr<IMedium> pImage; + size_t cImages = aImageList.size(); + bool fFound = false; + for (size_t i = 0; i < cImages; ++i) + { + pImage = aImageList[i]; + Bstr bstrImageId; + hrc = pImage->COMGETTER(Id)(bstrImageId.asOutParam()); + if (FAILED(hrc)) + continue; + + com::Guid imageId(bstrImageId); + + if (!imageId.isValid() || imageId.isZero()) + continue; + + if (!strImageId.compare(imageId.toString())) + { + fFound = true; + RTPrintf(Cloud::tr("Image %s was found\n"), strImageId.c_str()); + break; + } + } + + if (!fFound) + { + RTPrintf(Cloud::tr("Process of exporting the image to the Cloud was interrupted. The image wasn't found.\n")); + return RTEXITCODE_FAILURE; + } + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + ExportImage(pImage, ComSafeArrayAsInParam(parameters), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Export the image to the Cloud failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Export the image to the Cloud was successfull\n")); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE importCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "--bucket-name", 'b', RTGETOPT_REQ_STRING }, + { "--object-name", 'o', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strImageId; + Utf8Str strCompartmentId; + Utf8Str strBucketName; + Utf8Str strObjectName; + Utf8Str strDisplayName; + com::SafeArray<BSTR> parameters; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + strImageId=ValueUnion.psz; + break; + case 'b': + strBucketName=ValueUnion.psz; + Bstr(Utf8Str("bucket-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'o': + strObjectName=ValueUnion.psz; + Bstr(Utf8Str("object-name=").append(ValueUnion.psz)).detachTo(parameters.appendedRaw()); + break; + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Creating an object \'%s\' from the cloud image \'%s\'...\n"), strObjectName.c_str(), strImageId.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + ImportImage(Bstr(strImageId).raw(), ComSafeArrayAsInParam(parameters), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Cloud image import failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + { + RTPrintf(Cloud::tr("Cloud image was imported successfully. Find the downloaded object with the name %s " + "in the system temp folder (find the possible environment variables like TEMP, TMP and etc.)\n"), + strObjectName.c_str()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE showCloudImageInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strImageId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + strImageId = ValueUnion.psz; + break; + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Getting information about the cloud image with id \'%s\'...\n"), strImageId.c_str()); + + ComPtr<IStringArray> infoArray; + com::SafeArray<BSTR> pStrInfoArray; + ComPtr<IProgress> pProgress; + + RTPrintf(Cloud::tr("Reply is in the form \'image property\' = \'value\'\n")); + CHECK_ERROR2_RET(hrc, oCloudClient, + GetImageInfo(Bstr(strImageId).raw(), + infoArray.asOutParam(), + pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Cloud::tr("Getting information about the cloud image failed")), RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, + infoArray, COMGETTER(Values)(ComSafeArrayAsOutParam(pStrInfoArray)), + RTEXITCODE_FAILURE); + + RTPrintf(Cloud::tr("General information about the image:\n")); + size_t cParamNames = pStrInfoArray.size(); + for (size_t k = 0; k < cParamNames; k++) + { + Utf8Str data(pStrInfoArray[k]); + RTPrintf("\t%s\n", data.c_str()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE updateCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + RT_NOREF(a); + RT_NOREF(iFirst); + RT_NOREF(pCommonOpts); + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE deleteCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + Utf8Str strImageId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + { + if (strImageId.isNotEmpty()) + return errorArgument(Cloud::tr("Duplicate parameter: --id")); + + strImageId = ValueUnion.psz; + if (strImageId.isEmpty()) + return errorArgument(Cloud::tr("Empty parameter: --id")); + + break; + } + + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (strImageId.isEmpty()) + return errorArgument(Cloud::tr("Missing parameter: --id")); + + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + RTPrintf(Cloud::tr("Deleting cloud image with id %s...\n"), strImageId.c_str()); + + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + DeleteImage(Bstr(strImageId).raw(), progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Deleting cloud image failed")), RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud image was deleted successfully\n")); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE handleCloudImage(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + enum + { + kCloudImageIota = 1000, + kCloudImage_Create, + kCloudImage_Delete, + kCloudImage_Export, + kCloudImage_Import, + kCloudImage_Info, + kCloudImage_Update, + }; + + static const RTGETOPTDEF s_aOptions[] = + { + { "create", kCloudImage_Create, RTGETOPT_REQ_NOTHING }, + { "delete", kCloudImage_Delete, RTGETOPT_REQ_NOTHING }, + { "export", kCloudImage_Export, RTGETOPT_REQ_NOTHING }, + { "import", kCloudImage_Import, RTGETOPT_REQ_NOTHING }, + { "info", kCloudImage_Info, RTGETOPT_REQ_NOTHING }, + { "update", kCloudImage_Update, RTGETOPT_REQ_NOTHING }, + + { "help", 'h', RTGETOPT_REQ_NOTHING }, + { "-?", 'h', RTGETOPT_REQ_NOTHING }, + { "-help", 'h', RTGETOPT_REQ_NOTHING }, + { "--help", 'h', RTGETOPT_REQ_NOTHING }, + }; + + if (a->argc == iFirst) + { + RTPrintf(Cloud::tr("Empty command parameter list, show help.\n")); + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + /* Sub-commands: */ + case kCloudImage_Create: + setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_CREATE); + return createCloudImage(a, GetState.iNext, pCommonOpts); + + case kCloudImage_Export: + setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_EXPORT); + return exportCloudImage(a, GetState.iNext, pCommonOpts); + + case kCloudImage_Import: + setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_IMPORT); + return importCloudImage(a, GetState.iNext, pCommonOpts); + + case kCloudImage_Info: + setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_INFO); + return showCloudImageInfo(a, GetState.iNext, pCommonOpts); + + case kCloudImage_Update: +// setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_UPDATE); + return updateCloudImage(a, GetState.iNext, pCommonOpts); + + case kCloudImage_Delete: + setCurrentSubcommand(HELP_SCOPE_CLOUDIMAGE_DELETE); + return deleteCloudImage(a, GetState.iNext, pCommonOpts); + + case 'h': + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + return errorNoSubcommand(); +} + +#ifdef VBOX_WITH_CLOUD_NET +struct CloudNetworkOptions +{ + BOOL fEnable; + BOOL fDisable; + Bstr strNetworkId; + Bstr strNetworkName; +}; +typedef struct CloudNetworkOptions CLOUDNETOPT; +typedef CLOUDNETOPT *PCLOUDNETOPT; + +static RTEXITCODE createUpdateCloudNetworkCommon(ComPtr<ICloudNetwork> cloudNetwork, CLOUDNETOPT& options, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + Bstr strProvider = pCommonOpts->provider.pszProviderName; + Bstr strProfile = pCommonOpts->profile.pszProfileName; + + if (options.fEnable) + { + CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE); + } + if (options.fDisable) + { + CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE); + } + if (options.strNetworkId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(NetworkId)(options.strNetworkId.raw()), RTEXITCODE_FAILURE); + } + if (strProvider.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Provider)(strProvider.raw()), RTEXITCODE_FAILURE); + } + if (strProfile.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, cloudNetwork, COMSETTER(Profile)(strProfile.raw()), RTEXITCODE_FAILURE); + } + + return RTEXITCODE_SUCCESS; +} + + +static RTEXITCODE createCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + /* Required parameters, the rest is handled in update */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--disable", 'd', RTGETOPT_REQ_NOTHING }, + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "--network-id", 'i', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + }; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + CLOUDNETOPT options; + options.fEnable = FALSE; + options.fDisable = FALSE; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'd': + options.fDisable = TRUE; + break; + case 'e': + options.fEnable = TRUE; + break; + case 'i': + options.strNetworkId=ValueUnion.psz; + break; + case 'n': + options.strNetworkName=ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (options.strNetworkName.isEmpty()) + return errorArgument(Cloud::tr("Missing --name parameter")); + if (options.strNetworkId.isEmpty()) + return errorArgument(Cloud::tr("Missing --network-id parameter")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + ComPtr<ICloudNetwork> cloudNetwork; + CHECK_ERROR2_RET(hrc, pVirtualBox, + CreateCloudNetwork(options.strNetworkName.raw(), cloudNetwork.asOutParam()), + RTEXITCODE_FAILURE); + + /* Fill out the created network */ + RTEXITCODE rc = createUpdateCloudNetworkCommon(cloudNetwork, options, pCommonOpts); + if (RT_SUCCESS(rc)) + RTPrintf(Cloud::tr("Cloud network was created successfully\n")); + + return rc; +} + + +static RTEXITCODE showCloudNetworkInfo(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + RT_NOREF(pCommonOpts); + HRESULT hrc = S_OK; + static const RTGETOPTDEF s_aOptions[] = + { + { "--name", 'n', RTGETOPT_REQ_STRING }, + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + Bstr strNetworkName; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': + strNetworkName=ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (strNetworkName.isEmpty()) + return errorArgument(Cloud::tr("Missing --name parameter")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudNetwork> cloudNetwork; + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindCloudNetworkByName(strNetworkName.raw(), cloudNetwork.asOutParam()), + RTEXITCODE_FAILURE); + + RTPrintf(Cloud::tr("Name: %ls\n"), strNetworkName.raw()); + BOOL fEnabled = FALSE; + cloudNetwork->COMGETTER(Enabled)(&fEnabled); + RTPrintf(Cloud::tr("State: %s\n"), fEnabled ? Cloud::tr("Enabled") : Cloud::tr("Disabled")); + Bstr Provider; + cloudNetwork->COMGETTER(Provider)(Provider.asOutParam()); + RTPrintf(Cloud::tr("CloudProvider: %ls\n"), Provider.raw()); + Bstr Profile; + cloudNetwork->COMGETTER(Profile)(Profile.asOutParam()); + RTPrintf(Cloud::tr("CloudProfile: %ls\n"), Profile.raw()); + Bstr NetworkId; + cloudNetwork->COMGETTER(NetworkId)(NetworkId.asOutParam()); + RTPrintf(Cloud::tr("CloudNetworkId: %ls\n"), NetworkId.raw()); + Bstr netName = BstrFmt("cloud-%ls", strNetworkName.raw()); + RTPrintf(Cloud::tr("VBoxNetworkName: %ls\n\n"), netName.raw()); + + return RTEXITCODE_SUCCESS; +} + + +static RTEXITCODE updateCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--disable", 'd', RTGETOPT_REQ_NOTHING }, + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "--network-id", 'i', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + }; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + CLOUDNETOPT options; + options.fEnable = FALSE; + options.fDisable = FALSE; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'd': + options.fDisable = TRUE; + break; + case 'e': + options.fEnable = TRUE; + break; + case 'i': + options.strNetworkId=ValueUnion.psz; + break; + case 'n': + options.strNetworkName=ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (options.strNetworkName.isEmpty()) + return errorArgument(Cloud::tr("Missing --name parameter")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudNetwork> cloudNetwork; + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindCloudNetworkByName(options.strNetworkName.raw(), cloudNetwork.asOutParam()), + RTEXITCODE_FAILURE); + + RTEXITCODE rc = createUpdateCloudNetworkCommon(cloudNetwork, options, pCommonOpts); + if (RT_SUCCESS(rc)) + RTPrintf(Cloud::tr("Cloud network %ls was updated successfully\n"), options.strNetworkName.raw()); + + return rc; +} + + +static RTEXITCODE deleteCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + RT_NOREF(pCommonOpts); + HRESULT hrc = S_OK; + static const RTGETOPTDEF s_aOptions[] = + { + { "--name", 'n', RTGETOPT_REQ_STRING }, + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + Bstr strNetworkName; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': + strNetworkName=ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (strNetworkName.isEmpty()) + return errorArgument(Cloud::tr("Missing --name parameter")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudNetwork> cloudNetwork; + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindCloudNetworkByName(strNetworkName.raw(), cloudNetwork.asOutParam()), + RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, pVirtualBox, + RemoveCloudNetwork(cloudNetwork), + RTEXITCODE_FAILURE); + + if (SUCCEEDED(hrc)) + RTPrintf(Cloud::tr("Cloud network %ls was deleted successfully\n"), strNetworkName.raw()); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static RTEXITCODE setupCloudNetworkEnv(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + RT_NOREF(pCommonOpts); + HRESULT hrc = S_OK; + static const RTGETOPTDEF s_aOptions[] = + { + { "--gateway-os-name", 'n', RTGETOPT_REQ_STRING }, + { "--gateway-os-version", 'v', RTGETOPT_REQ_STRING }, + { "--gateway-shape", 's', RTGETOPT_REQ_STRING }, + { "--tunnel-network-name", 't', RTGETOPT_REQ_STRING }, + { "--tunnel-network-range", 'r', RTGETOPT_REQ_STRING }, + { "--compartment-id", 'c', RTGETOPT_REQ_STRING } + }; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + Bstr strGatewayOsName; + Bstr strGatewayOsVersion; + Bstr strGatewayShape; + Bstr strTunnelNetworkName; + Bstr strTunnelNetworkRange; + Bstr strCompartmentId; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': + strGatewayOsName=ValueUnion.psz; + break; + case 'v': + strGatewayOsVersion=ValueUnion.psz; + break; + case 's': + strGatewayShape=ValueUnion.psz; + break; + case 't': + strTunnelNetworkName=ValueUnion.psz; + break; + case 'r': + strTunnelNetworkRange=ValueUnion.psz; + break; + case 'c': + strCompartmentId=ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Delayed check. It allows us to print help information.*/ + hrc = checkAndSetCommonOptions(a, pCommonOpts); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + RTPrintf(Cloud::tr("Setting up tunnel network in the cloud...\n")); + + ComPtr<ICloudProfile> pCloudProfile = pCommonOpts->profile.pCloudProfile; + + /* Use user-specified profile instead of default one. */ + if (strCompartmentId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, pCloudProfile, + SetProperty(Bstr("compartment").raw(), Bstr(strCompartmentId).raw()), + RTEXITCODE_FAILURE); + } + + ComObjPtr<ICloudClient> oCloudClient; + CHECK_ERROR2_RET(hrc, pCloudProfile, + CreateCloudClient(oCloudClient.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudNetworkEnvironmentInfo> cloudNetworkEnv; + ComPtr<IProgress> progress; + CHECK_ERROR2_RET(hrc, oCloudClient, + SetupCloudNetworkEnvironment(strTunnelNetworkName.raw(), strTunnelNetworkRange.raw(), + strGatewayOsName.raw(), strGatewayOsVersion.raw(), strGatewayShape.raw(), + cloudNetworkEnv.asOutParam(), progress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Cloud::tr("Setting up cloud network environment failed")), RTEXITCODE_FAILURE); + + Bstr tunnelNetworkId; + hrc = cloudNetworkEnv->COMGETTER(TunnelNetworkId)(tunnelNetworkId.asOutParam()); + RTPrintf(Cloud::tr("Cloud network environment was set up successfully. Tunnel network id is: %ls\n"), tunnelNetworkId.raw()); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static RTEXITCODE handleCloudNetwork(HandlerArg *a, int iFirst, PCLOUDCOMMONOPT pCommonOpts) +{ + enum + { + kCloudNetworkIota = 1000, + kCloudNetwork_Create, + kCloudNetwork_Delete, + kCloudNetwork_Info, + kCloudNetwork_Setup, + kCloudNetwork_Update, + }; + + static const RTGETOPTDEF s_aOptions[] = + { + { "create", kCloudNetwork_Create, RTGETOPT_REQ_NOTHING }, + { "delete", kCloudNetwork_Delete, RTGETOPT_REQ_NOTHING }, + { "info", kCloudNetwork_Info, RTGETOPT_REQ_NOTHING }, + { "setup", kCloudNetwork_Setup, RTGETOPT_REQ_NOTHING }, + { "update", kCloudNetwork_Update, RTGETOPT_REQ_NOTHING }, + }; + + if (a->argc < 1) + return errorNoSubcommand(); + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + /* Sub-commands: */ + case kCloudNetwork_Create: + return createCloudNetwork(a, GetState.iNext, pCommonOpts); + + case kCloudNetwork_Info: + return showCloudNetworkInfo(a, GetState.iNext, pCommonOpts); + + case kCloudNetwork_Update: + return updateCloudNetwork(a, GetState.iNext, pCommonOpts); + + case kCloudNetwork_Delete: + return deleteCloudNetwork(a, GetState.iNext, pCommonOpts); + + case kCloudNetwork_Setup: + return setupCloudNetworkEnv(a, GetState.iNext, pCommonOpts); + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + return errorNoSubcommand(); +} +#endif /* VBOX_WITH_CLOUD_NET */ + + +RTEXITCODE handleCloud(HandlerArg *a) +{ + enum + { + kCloudIota = 1000, + kCloud_Image, + kCloud_Instance, + kCloud_List, + kCloud_Machine, + kCloud_Network, + kCloud_Object, + kCloud_ShowVMInfo, + kCloud_Volume, + }; + + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--provider", 'v', RTGETOPT_REQ_STRING }, + { "--profile", 'f', RTGETOPT_REQ_STRING }, + + { "image", kCloud_Image, RTGETOPT_REQ_NOTHING }, + { "instance", kCloud_Instance, RTGETOPT_REQ_NOTHING }, + { "list", kCloud_List, RTGETOPT_REQ_NOTHING }, + { "machine", kCloud_Machine, RTGETOPT_REQ_NOTHING }, + { "network", kCloud_Network, RTGETOPT_REQ_NOTHING }, + { "object", kCloud_Object, RTGETOPT_REQ_NOTHING }, + { "showvminfo", kCloud_ShowVMInfo, RTGETOPT_REQ_NOTHING }, + { "volume", kCloud_Volume, RTGETOPT_REQ_NOTHING }, + }; + + if (a->argc < 1) + return errorNoSubcommand(); + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + CLOUDCOMMONOPT commonOpts = { {NULL, NULL}, {NULL, NULL} }; + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'v': // --provider + commonOpts.provider.pszProviderName = ValueUnion.psz; + break; + + case 'f': // --profile + commonOpts.profile.pszProfileName = ValueUnion.psz; + break; + + /* Sub-commands: */ + case kCloud_List: + return handleCloudLists(a, GetState.iNext, &commonOpts); + + case kCloud_Image: + return handleCloudImage(a, GetState.iNext, &commonOpts); + + case kCloud_Instance: + return handleCloudInstance(a, GetState.iNext, &commonOpts); + +#ifdef VBOX_WITH_CLOUD_NET + case kCloud_Network: + return handleCloudNetwork(a, GetState.iNext, &commonOpts); +#endif /* VBOX_WITH_CLOUD_NET */ + + /* "cloud machine ..." handling is in VBoxManageCloudMachine.cpp */ + case kCloud_Machine: + return handleCloudMachine(a, GetState.iNext, + commonOpts.provider.pszProviderName, + commonOpts.profile.pszProfileName); + + /* ... including aliases that mimic the local vm commands */ + case kCloud_ShowVMInfo: + return handleCloudShowVMInfo(a, GetState.iNext, + commonOpts.provider.pszProviderName, + commonOpts.profile.pszProfileName); + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + return errorNoSubcommand(); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageCloudMachine.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageCloudMachine.cpp new file mode 100644 index 00000000..78223337 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageCloudMachine.cpp @@ -0,0 +1,1482 @@ +/* $Id: VBoxManageCloudMachine.cpp $ */ +/** @file + * VBoxManageCloudMachine - The cloud machine related commands. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "VBoxManage.h" + +#include <VBox/log.h> + +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/Guid.h> +#include <VBox/com/errorprint.h> + +#include <algorithm> +#include <vector> + +DECLARE_TRANSLATION_CONTEXT(CloudMachine); + + +struct CMachineHandlerArg + : public HandlerArg +{ + ComPtr<ICloudClient> pClient; + + const char *pcszSpec; /* RTGETOPTUNION::psz, points inside argv */ + enum { GUESS, ID, NAME } enmSpecKind; + ComPtr<ICloudMachine> pMachine; + + explicit CMachineHandlerArg(const HandlerArg &a) + : HandlerArg(a), pcszSpec(NULL), enmSpecKind(GUESS) {} +}; + + +static int selectCloudProvider(ComPtr<ICloudProvider> &pProvider, + const ComPtr<IVirtualBox> &pVirtualBox, + const char *pszProviderName); +static int selectCloudProfile(ComPtr<ICloudProfile> &pProfile, + const ComPtr<ICloudProvider> &pProvider, + const char *pszProviderName); +static int getCloudClient(CMachineHandlerArg &a, + const char *pcszProviderName, + const char *pcszProfileName); + +static HRESULT getMachineList(com::SafeIfaceArray<ICloudMachine> &aMachines, + const ComPtr<ICloudClient> &pClient); + +static HRESULT getMachineBySpec(CMachineHandlerArg *a); +static HRESULT getMachineById(CMachineHandlerArg *a); +static HRESULT getMachineByName(CMachineHandlerArg *a); +static HRESULT getMachineByGuess(CMachineHandlerArg *a); + +static int checkMachineSpecArgument(CMachineHandlerArg *a, + int ch, const RTGETOPTUNION &Val); + + +static RTEXITCODE handleCloudMachineImpl(CMachineHandlerArg *a, int iFirst); + +static RTEXITCODE handleCloudMachineStart(CMachineHandlerArg *a, int iFirst); +static RTEXITCODE handleCloudMachineReboot(CMachineHandlerArg *a, int iFirst); +static RTEXITCODE handleCloudMachineReset(CMachineHandlerArg *a, int iFirst); +static RTEXITCODE handleCloudMachineShutdown(CMachineHandlerArg *a, int iFirst); +static RTEXITCODE handleCloudMachinePowerdown(CMachineHandlerArg *a, int iFirst); +static RTEXITCODE handleCloudMachineTerminate(CMachineHandlerArg *a, int iFirst); + +static RTEXITCODE handleCloudMachineConsoleHistory(CMachineHandlerArg *a, int iFirst); + +static RTEXITCODE listCloudMachinesImpl(CMachineHandlerArg *a, int iFirst); +static RTEXITCODE handleCloudMachineInfo(CMachineHandlerArg *a, int iFirst); + +static HRESULT printMachineInfo(const ComPtr<ICloudMachine> &pMachine); +static HRESULT printFormValue(const ComPtr<IFormValue> &pValue); + + + +/* + * This is a temporary hack as I don't want to refactor "cloud" + * handling right now, as it's not yet clear to me what is the + * direction that we want to take with it. + * + * The problem with the way "cloud" command handling is currently + * written is that it's a bit schizophrenic about whether we have + * multiple cloud providers or not. OTOH it insists on --provider + * being mandatory, on the other it hardcodes the list of available + * subcommands, though in principle those can vary from provider to + * provider. If we do want to support multiple providers we might + * need to come up with a way to allow an extpack provider to supply + * its own VBoxManage command handler for "cloud" based on --provider + * as the selector. + * + * Processing of --provider and --profile should not be postponed + * until the leaf command handler, but rather happen immediately, so + * do this here at our earliest opportunity (without actually doing it + * in handleCloud). + */ +RTEXITCODE +handleCloudMachine(HandlerArg *a, int iFirst, + const char *pcszProviderName, + const char *pcszProfileName) +{ + CMachineHandlerArg handlerArg(*a); + int vrc = getCloudClient(handlerArg, pcszProviderName, pcszProfileName); + if (RT_FAILURE(vrc)) + return RTEXITCODE_FAILURE; + + return handleCloudMachineImpl(&handlerArg, iFirst); +} + + +/* + * Select cloud provider to use based on the --provider option to the + * "cloud" command. The option is not mandatory if only a single + * provider is available. + */ +static int +selectCloudProvider(ComPtr<ICloudProvider> &pProvider, + const ComPtr<IVirtualBox> &pVirtualBox, + const char *pcszProviderName) +{ + HRESULT hrc; + + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + VERR_GENERAL_FAILURE); + + + /* + * If the provider is explicitly specified, just look it up and + * return. + */ + if (pcszProviderName != NULL) + { + /* + * Should we also provide a way to specify the provider also + * by its id? Is it even useful? If so, should we use a + * different option or check if the provider name looks like + * an id and used a different getter? + */ + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(com::Bstr(pcszProviderName).raw(), + pProvider.asOutParam()), + VERR_NOT_FOUND); + + return VINF_SUCCESS; + } + + + /* + * We have only one provider and it's not clear if we will ever + * have more than one. Forcing the user to explicitly specify the + * only provider available is not very nice. So try to be + * friendly. + */ + com::SafeIfaceArray<ICloudProvider> aProviders; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + COMGETTER(Providers)(ComSafeArrayAsOutParam(aProviders)), + VERR_GENERAL_FAILURE); + + if (aProviders.size() == 0) + { + RTMsgError(CloudMachine::tr("cloud: no providers available")); + return VERR_NOT_FOUND; + } + + if (aProviders.size() > 1) + { + RTMsgError(CloudMachine::tr("cloud: multiple providers available," + " '--provider' option is required")); + return VERR_MISSING; + } + + /* Do RTMsgInfo telling the user which one was selected? */ + pProvider = aProviders[0]; + return VINF_SUCCESS; +} + + +/* + * Select cloud profile to use based on the --profile option to the + * "cloud" command. The option is not mandatory if only a single + * profile exists. + */ +static int +selectCloudProfile(ComPtr<ICloudProfile> &pProfile, + const ComPtr<ICloudProvider> &pProvider, + const char *pcszProfileName) +{ + HRESULT hrc; + + /* + * If the profile is explicitly specified, just look it up and + * return. + */ + if (pcszProfileName != NULL) + { + CHECK_ERROR2_RET(hrc, pProvider, + GetProfileByName(com::Bstr(pcszProfileName).raw(), + pProfile.asOutParam()), + VERR_NOT_FOUND); + + return VINF_SUCCESS; + } + + + /* + * If the user has just one profile for this provider, don't force + * them to specify it. I'm not entirely sure about this one, + * actually. It's nice for interactive use, but it might be not + * forward compatible if used in a script and then when another + * profile is created the script starts failing. I'd say, give + * them enough rope... + */ + com::SafeIfaceArray<ICloudProfile> aProfiles; + CHECK_ERROR2_RET(hrc, pProvider, + COMGETTER(Profiles)(ComSafeArrayAsOutParam(aProfiles)), + VERR_GENERAL_FAILURE); + + if (aProfiles.size() == 0) + { + RTMsgError(CloudMachine::tr("cloud: no profiles exist")); + return VERR_NOT_FOUND; + } + + if (aProfiles.size() > 1) + { + RTMsgError(CloudMachine::tr("cloud: multiple profiles exist, '--profile' option is required")); + return VERR_MISSING; + } + + /* Do RTMsgInfo telling the user which one was selected? */ + pProfile = aProfiles[0]; + return VINF_SUCCESS; +} + + +static int +getCloudClient(CMachineHandlerArg &a, + const char *pcszProviderName, + const char *pcszProfileName) +{ + ComPtr<ICloudProvider> pProvider; + int vrc = selectCloudProvider(pProvider, a.virtualBox, pcszProviderName); + if (RT_FAILURE(vrc)) + return vrc; + + ComPtr<ICloudProfile> pProfile; + vrc = selectCloudProfile(pProfile, pProvider, pcszProfileName); + if (RT_FAILURE(vrc)) + return vrc; + + ComPtr<ICloudClient> pCloudClient; + CHECK_ERROR2I_RET(pProfile, CreateCloudClient(pCloudClient.asOutParam()), VERR_GENERAL_FAILURE); + + a.pClient = pCloudClient; + return VINF_SUCCESS; +} + + +static HRESULT +getMachineList(com::SafeIfaceArray<ICloudMachine> &aMachines, + const ComPtr<ICloudClient> &pClient) +{ + HRESULT hrc; + + ComPtr<IProgress> pListProgress; + CHECK_ERROR2_RET(hrc, pClient, + ReadCloudMachineList(pListProgress.asOutParam()), + hrc); + + hrc = showProgress(pListProgress, SHOW_PROGRESS_NONE); + if (FAILED(hrc)) + return hrc; + + CHECK_ERROR2_RET(hrc, pClient, + COMGETTER(CloudMachineList)(ComSafeArrayAsOutParam(aMachines)), + hrc); + + return S_OK; +} + + +static HRESULT +getMachineById(CMachineHandlerArg *a) +{ + HRESULT hrc; + + ComPtr<ICloudMachine> pMachine; + CHECK_ERROR2_RET(hrc, a->pClient, + GetCloudMachine(com::Bstr(a->pcszSpec).raw(), + pMachine.asOutParam()), hrc); + + ComPtr<IProgress> pRefreshProgress; + CHECK_ERROR2_RET(hrc, pMachine, + Refresh(pRefreshProgress.asOutParam()), hrc); + + hrc = showProgress(pRefreshProgress, SHOW_PROGRESS_NONE); + if (FAILED(hrc)) + return hrc; + + a->pMachine = pMachine; + return S_OK; +} + + +static HRESULT +getMachineByName(CMachineHandlerArg *a) +{ + HRESULT hrc; + + com::SafeIfaceArray<ICloudMachine> aMachines; + hrc = getMachineList(aMachines, a->pClient); + if (FAILED(hrc)) + return hrc; + + const size_t cMachines = aMachines.size(); + if (cMachines == 0) + return VBOX_E_OBJECT_NOT_FOUND; + + ComPtr<ICloudMachine> pMachineFound; + for (size_t i = 0; i < cMachines; ++i) + { + const ComPtr<ICloudMachine> pMachine = aMachines[i]; + + com::Bstr bstrName; + CHECK_ERROR2_RET(hrc, pMachine, + COMGETTER(Name)(bstrName.asOutParam()), + hrc); + + if (!bstrName.equals(a->pcszSpec)) + continue; + + if (pMachineFound.isNull()) + pMachineFound = pMachine; + else + { + com::Bstr bstrId1, bstrId2; + CHECK_ERROR2_RET(hrc, pMachineFound, + COMGETTER(Id)(bstrId1.asOutParam()), + hrc); + CHECK_ERROR2_RET(hrc, pMachine, + COMGETTER(Id)(bstrId2.asOutParam()), + hrc); + + RTMsgError(CloudMachine::tr("ambiguous name: %ls and %ls"), bstrId1.raw(), bstrId2.raw()); + return VBOX_E_OBJECT_NOT_FOUND; + } + } + + if (pMachineFound.isNull()) + return VBOX_E_OBJECT_NOT_FOUND; + + a->pMachine = pMachineFound; + return S_OK; +} + + +/* + * Try to find the machine refered by pcszWhatever. If the look up by + * id fails we might want to fallback to look up by name, b/c someone + * might want to use a uuid as a display name of a machine. But cloud + * lookups are not fast, so that would be incurring performance + * penalty for typos or for machines that are gone. Should provide + * explicit --id/--name options instead. + */ +static HRESULT +getMachineByGuess(CMachineHandlerArg *a) +{ + HRESULT hrc; + + RTUUID Uuid; + int vrc = RTUuidFromStr(&Uuid, a->pcszSpec); + if (RT_SUCCESS(vrc)) + hrc = getMachineById(a); + else + hrc = getMachineByName(a); + + if (FAILED(hrc)) + return hrc; + + return S_OK; +} + + + +/* + * RTGETOPTINIT_FLAGS_NO_STD_OPTS recognizes both --help and --version + * and we don't want the latter. It's easier to add one line of this + * macro to the s_aOptions initializers than to filter out --version. + */ +#define CLOUD_MACHINE_RTGETOPTDEF_HELP \ + { "--help", 'h', RTGETOPT_REQ_NOTHING }, \ + { "-help", 'h', RTGETOPT_REQ_NOTHING }, \ + { "help", 'h', RTGETOPT_REQ_NOTHING }, \ + { "-?", 'h', RTGETOPT_REQ_NOTHING } + +static RTEXITCODE +errThereCanBeOnlyOne() +{ + return RTMsgErrorExit(RTEXITCODE_SYNTAX, + CloudMachine::tr("only one machine can be specified")); +} + + +#define CLOUD_MACHINE_RTGETOPTDEF_MACHINE \ + { "--id", 'i', RTGETOPT_REQ_STRING }, \ + { "--name", 'n', RTGETOPT_REQ_STRING } + + +/* + * Almost all the cloud machine commands take a machine argument, so + * factor out the code to fish it out from the command line. + * + * ch - option should be processed by the caller. + * VINF_SUCCESS - option was processed. + * VERR_PARSE_ERROR - RTEXITCODE_SYNTAX + * Other IPRT errors - RTEXITCODE_FAILURE + */ +static int +checkMachineSpecArgument(CMachineHandlerArg *a, + int ch, const RTGETOPTUNION &Val) +{ + int vrc; + + switch (ch) + { + /* + * Note that we don't used RTGETOPT_REQ_UUID here as it would + * be too limiting. First, we need the original string for + * the API call, not the UUID, and second, if the UUID has bad + * forward RTGetOptPrintError doesn't have access to the + * option argument for the error message. So do the format + * check ourselves. + */ + case 'i': /* --id */ + { + const char *pcszId = Val.psz; + + if (a->pcszSpec != NULL) + { + errThereCanBeOnlyOne(); + return VERR_PARSE_ERROR; + } + + RTUUID Uuid; + vrc = RTUuidFromStr(&Uuid, pcszId); + if (RT_FAILURE(vrc)) + { + RTMsgError(CloudMachine::tr("not a valid uuid: %s"), pcszId); + return VERR_PARSE_ERROR; + } + + a->pcszSpec = pcszId; + a->enmSpecKind = CMachineHandlerArg::ID; + return VINF_SUCCESS; + } + + case 'n': /* --name */ + { + const char *pcszName = Val.psz; + + if (a->pcszSpec != NULL) + { + errThereCanBeOnlyOne(); + return VERR_PARSE_ERROR; + } + + a->pcszSpec = pcszName; + a->enmSpecKind = CMachineHandlerArg::NAME; + return VINF_SUCCESS; + } + + /* + * Plain word (no dash/es). This must name a machine, though + * we have to guess whether it's an id or a name. + */ + case VINF_GETOPT_NOT_OPTION: + { + const char *pcszNameOrId = Val.psz; + + if (a->pcszSpec != NULL) + { + errThereCanBeOnlyOne(); + return VERR_PARSE_ERROR; + } + + a->pcszSpec = pcszNameOrId; + a->enmSpecKind = CMachineHandlerArg::GUESS; + return VINF_SUCCESS; + } + + /* might as well do it here */ + case 'h': /* --help */ + { + printHelp(g_pStdOut); + return VINF_CALLBACK_RETURN; + } + } + + /* let the caller deal with it */ + return VINF_NOT_SUPPORTED; +} + + +static HRESULT +getMachineBySpec(CMachineHandlerArg *a) +{ + HRESULT hrc = E_FAIL; + + if (a->pcszSpec == NULL) + { + RTMsgErrorExit(RTEXITCODE_SYNTAX, CloudMachine::tr("machine not specified")); + return E_FAIL; + } + + if (a->pcszSpec[0] == '\0') + { + RTMsgError(CloudMachine::tr("machine name is empty")); + return E_FAIL; + } + + switch (a->enmSpecKind) + { + case CMachineHandlerArg::ID: + hrc = getMachineById(a); + if (FAILED(hrc)) + { + if (hrc == VBOX_E_OBJECT_NOT_FOUND) + RTMsgError(CloudMachine::tr("unable to find machine with id %s"), a->pcszSpec); + return hrc; + } + break; + + case CMachineHandlerArg::NAME: + hrc = getMachineByName(a); + if (FAILED(hrc)) + { + if (hrc == VBOX_E_OBJECT_NOT_FOUND) + RTMsgError(CloudMachine::tr("unable to find machine with name %s"), a->pcszSpec); + return hrc; + } + break; + + case CMachineHandlerArg::GUESS: + hrc = getMachineByGuess(a); + if (FAILED(hrc)) + { + if (hrc == VBOX_E_OBJECT_NOT_FOUND) + RTMsgError(CloudMachine::tr("unable to find machine %s"), a->pcszSpec); + return hrc; + } + break; + } + + /* switch was exhaustive (and successful) */ + AssertReturn(SUCCEEDED(hrc), E_FAIL); + return S_OK; +} + + + + +/* + * cloud machine [--id id | --name name] command ... + * + * We allow machine to be specified after "machine" but only with an + * explicit option for the obvious reason. We will also check for + * these options and machine spec as a plain words argument after the + * command word, so user can use either of: + * + * cloud machine --name foo start + * cloud machine start --name foo + * cloud machine start foo + * + * This will accept e.g. cloud machine --name foo list ... b/c we + * don't yet know that it's "list" that is coming, so commands that + * don't take machine argument check that separately when called. One + * side effect of this is that specifying several machines or using a + * syntactically invalid id will be reported as such, not as an + * unknown option, but that's a relatively minor nit. + */ +static RTEXITCODE +handleCloudMachineImpl(CMachineHandlerArg *a, int iFirst) +{ + enum + { + kMachineIota = 1000, + kMachine_ConsoleHistory, + kMachine_Info, + kMachine_List, + kMachine_Powerdown, + kMachine_Reboot, + kMachine_Reset, + kMachine_Shutdown, + kMachine_Start, + kMachine_Terminate, + }; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE); + static const RTGETOPTDEF s_aOptions[] = + { + { "console-history", kMachine_ConsoleHistory, RTGETOPT_REQ_NOTHING }, + { "consolehistory", kMachine_ConsoleHistory, RTGETOPT_REQ_NOTHING }, + { "info", kMachine_Info, RTGETOPT_REQ_NOTHING }, + { "list", kMachine_List, RTGETOPT_REQ_NOTHING }, + { "powerdown", kMachine_Powerdown, RTGETOPT_REQ_NOTHING }, + { "reboot", kMachine_Reboot, RTGETOPT_REQ_NOTHING }, + { "reset", kMachine_Reset, RTGETOPT_REQ_NOTHING }, + { "shutdown", kMachine_Shutdown, RTGETOPT_REQ_NOTHING }, + { "start", kMachine_Start, RTGETOPT_REQ_NOTHING }, + { "terminate", kMachine_Terminate, RTGETOPT_REQ_NOTHING }, + CLOUD_MACHINE_RTGETOPTDEF_MACHINE, + CLOUD_MACHINE_RTGETOPTDEF_HELP + }; + + RTGETOPTSTATE OptState; + int vrc = RTGetOptInit(&OptState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), + iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + AssertRCReturn(vrc, RTMsgErrorExit(RTEXITCODE_INIT, CloudMachine::tr("cloud machine: RTGetOptInit: %Rra"), vrc)); + + int ch; + RTGETOPTUNION Val; + while ((ch = RTGetOpt(&OptState, &Val)) != 0) + { + if (RT_FAILURE(ch)) + return RTGetOptPrintError(ch, &Val); + + /* + * Check for an unknown word first: checkMachineSpecArgument() + * would try to interpret that as a machine id/name. + */ + if (ch == VINF_GETOPT_NOT_OPTION) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, + CloudMachine::tr("Invalid sub-command: %s"), Val.psz); + + /* + * Allow --id/--name after "machine", before the command. + * Also handles --help. + */ + vrc = checkMachineSpecArgument(a, ch, Val); + if (vrc == VINF_SUCCESS) + continue; + if (vrc == VINF_CALLBACK_RETURN) + return RTEXITCODE_SUCCESS; + if (vrc == VERR_PARSE_ERROR) + return RTEXITCODE_SYNTAX; + + /* + * Dispatch to command implementation ([ab]use getopt to do + * string comparisons for us). + */ + switch (ch) + { + case kMachine_ConsoleHistory: + return handleCloudMachineConsoleHistory(a, OptState.iNext); + + case kMachine_Info: + return handleCloudMachineInfo(a, OptState.iNext); + + case kMachine_List: + return listCloudMachinesImpl(a, OptState.iNext); + + case kMachine_Powerdown: + return handleCloudMachinePowerdown(a, OptState.iNext); + + case kMachine_Reboot: + return handleCloudMachineReboot(a, OptState.iNext); + + case kMachine_Reset: + return handleCloudMachineReset(a, OptState.iNext); + + case kMachine_Shutdown: + return handleCloudMachineShutdown(a, OptState.iNext); + + case kMachine_Start: + return handleCloudMachineStart(a, OptState.iNext); + + case kMachine_Terminate: + return handleCloudMachineTerminate(a, OptState.iNext); + + default: /* should never happen */ + return RTMsgErrorExit(RTEXITCODE_INIT, + CloudMachine::tr("cloud machine: internal error: %d"), ch); + } + } + + return RTMsgErrorExit(RTEXITCODE_SYNTAX, + CloudMachine::tr("cloud machine: command required\n" + "Try '--help' for more information.")); +} + + +/* + * cloud list machines + * + * The "cloud list" prefix handling is in VBoxManageCloud.cpp, so this + * function is not static. See handleCloudMachine() for the + * explanation early provider/profile lookup. + */ +RTEXITCODE +listCloudMachines(HandlerArg *a, int iFirst, + const char *pcszProviderName, + const char *pcszProfileName) +{ + CMachineHandlerArg handlerArg(*a); + int vrc = getCloudClient(handlerArg, pcszProviderName, pcszProfileName); + if (RT_FAILURE(vrc)) + return RTEXITCODE_FAILURE; + + return listCloudMachinesImpl(&handlerArg, iFirst); +} + + +/* + * cloud machine list # convenience alias + * cloud list machines # see above + */ +static RTEXITCODE +listCloudMachinesImpl(CMachineHandlerArg *a, int iFirst) +{ + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_LIST); + static const RTGETOPTDEF s_aOptions[] = + { + { "--long", 'l', RTGETOPT_REQ_NOTHING }, + { "--sort", 's', RTGETOPT_REQ_NOTHING }, + CLOUD_MACHINE_RTGETOPTDEF_HELP + }; + + enum kFormatEnum { kFormat_Short, kFormat_Long }; + kFormatEnum enmFormat = kFormat_Short; + + enum kSortOrderEnum { kSortOrder_None, kSortOrder_Name, kSortOrder_Id }; + kSortOrderEnum enmSortOrder = kSortOrder_None; + + if (a->pcszSpec != NULL) + return RTMsgErrorExit(RTEXITCODE_SYNTAX, + CloudMachine::tr("cloud machine list: unexpected machine argument")); + + + RTGETOPTSTATE OptState; + int vrc = RTGetOptInit(&OptState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), + iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + AssertRCReturn(vrc, RTMsgErrorExit(RTEXITCODE_INIT, CloudMachine::tr("cloud machine list: RTGetOptInit: %Rra"), vrc)); + + int ch; + RTGETOPTUNION Val; + while ((ch = RTGetOpt(&OptState, &Val)) != 0) + { + switch (ch) + { + case 'l': + enmFormat = kFormat_Long; + break; + + case 's': + /** @todo optional argument to select the sort key? */ + enmSortOrder = kSortOrder_Name; + break; + + case 'h': /* --help */ + printHelp(g_pStdOut); + return RTEXITCODE_SUCCESS; + + + case VINF_GETOPT_NOT_OPTION: + return RTMsgErrorExit(RTEXITCODE_SYNTAX, + CloudMachine::tr("Invalid sub-command: %s"), Val.psz); + + default: + return RTGetOptPrintError(ch, &Val); + } + } + + com::SafeIfaceArray<ICloudMachine> aMachines; + HRESULT hrc = getMachineList(aMachines, a->pClient); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + const size_t cMachines = aMachines.size(); + if (cMachines == 0) + return RTEXITCODE_SUCCESS; + + + /* + * Get names/ids that we need for the short output and to sort the + * list. + */ + std::vector<ComPtr<ICloudMachine> > vMachines(cMachines); + std::vector<com::Bstr> vBstrNames(cMachines); + std::vector<com::Bstr> vBstrIds(cMachines); + for (size_t i = 0; i < cMachines; ++i) + { + vMachines[i] = aMachines[i]; + + CHECK_ERROR2_RET(hrc, vMachines[i], + COMGETTER(Name)(vBstrNames[i].asOutParam()), + RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, vMachines[i], + COMGETTER(Id)(vBstrIds[i].asOutParam()), + RTEXITCODE_FAILURE); + } + + + /* + * Sort the list if necessary. The sort is indirect via an + * intermediate array of indexes. + */ + std::vector<size_t> vIndexes(cMachines); + for (size_t i = 0; i < cMachines; ++i) + vIndexes[i] = i; + + if (enmSortOrder != kSortOrder_None) + { + struct SortBy { + const std::vector<com::Bstr> &ks; + SortBy(const std::vector<com::Bstr> &aKeys) : ks(aKeys) {} + bool operator() (size_t l, size_t r) { return ks[l] < ks[r]; } + }; + + std::sort(vIndexes.begin(), vIndexes.end(), + SortBy(enmSortOrder == kSortOrder_Name + ? vBstrNames : vBstrIds)); + } + + + if (enmFormat == kFormat_Short) + { + for (size_t i = 0; i < cMachines; ++i) + { + const size_t idx = vIndexes[i]; + const com::Bstr &bstrId = vBstrIds[idx]; + const com::Bstr &bstrName = vBstrNames[idx]; + + RTPrintf("%ls %ls\n", bstrId.raw(), bstrName.raw()); + } + } + else // kFormat_Long + { + for (size_t i = 0; i < cMachines; ++i) + { + const size_t idx = vIndexes[i]; + const ComPtr<ICloudMachine> &pMachine = vMachines[idx]; + + if (i != 0) + RTPrintf("\n"); + printMachineInfo(pMachine); + } + } + + return RTEXITCODE_SUCCESS; +} + + +/* + * cloud showvminfo "id" + * + * Alias for "cloud machine info" that tries to match the local vm + * counterpart. + */ +RTEXITCODE +handleCloudShowVMInfo(HandlerArg *a, int iFirst, + const char *pcszProviderName, + const char *pcszProfileName) +{ + CMachineHandlerArg handlerArg(*a); + int vrc = getCloudClient(handlerArg, pcszProviderName, pcszProfileName); + if (RT_FAILURE(vrc)) + return RTEXITCODE_FAILURE; + + return handleCloudMachineInfo(&handlerArg, iFirst); +} + + +/* + * cloud machine info "id" ... + */ +static RTEXITCODE +handleCloudMachineInfo(CMachineHandlerArg *a, int iFirst) +{ + enum + { + kMachineInfoIota = 1000, + kMachineInfo_Details, + }; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_INFO); + static const RTGETOPTDEF s_aOptions[] = + { + { "--details", kMachineInfo_Details, RTGETOPT_REQ_NOTHING }, + CLOUD_MACHINE_RTGETOPTDEF_MACHINE, + CLOUD_MACHINE_RTGETOPTDEF_HELP + }; + + RTGETOPTSTATE OptState; + int vrc = RTGetOptInit(&OptState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), + iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + AssertRCReturn(vrc, RTMsgErrorExit(RTEXITCODE_INIT, "RTGetOptInit: %Rra", vrc)); + + int ch; + RTGETOPTUNION Val; + while ((ch = RTGetOpt(&OptState, &Val)) != 0) + { + vrc = checkMachineSpecArgument(a, ch, Val); + if (vrc == VINF_SUCCESS) + continue; + if (vrc == VINF_CALLBACK_RETURN) + return RTEXITCODE_SUCCESS; + if (vrc == VERR_PARSE_ERROR) + return RTEXITCODE_SYNTAX; + + switch (ch) + { + case kMachineInfo_Details: + /* currently no-op */ + break; + + default: + return RTGetOptPrintError(ch, &Val); + } + } + + HRESULT hrc = getMachineBySpec(a); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + /* end of boilerplate */ + + + hrc = printMachineInfo(a->pMachine); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + return RTEXITCODE_SUCCESS; +} + + +static HRESULT +printMachineInfo(const ComPtr<ICloudMachine> &pMachine) +{ + HRESULT hrc; + + com::Bstr bstrId; + CHECK_ERROR2_RET(hrc, pMachine, + COMGETTER(Id)(bstrId.asOutParam()), + hrc); + RTPrintf("UUID: %ls\n", bstrId.raw()); + + + /* + * Check if the machine is accessible and print the error + * message if not. + */ + BOOL fAccessible = FALSE; + CHECK_ERROR2_RET(hrc, pMachine, + COMGETTER(Accessible)(&fAccessible), hrc); + + if (!fAccessible) + { + RTMsgError(CloudMachine::tr("machine is not accessible")); // XXX: Id? + + ComPtr<IVirtualBoxErrorInfo> pErrorInfo; + CHECK_ERROR2_RET(hrc, pMachine, + COMGETTER(AccessError)(pErrorInfo.asOutParam()), hrc); + + while (!pErrorInfo.isNull()) + { + com::Bstr bstrText; + CHECK_ERROR2_RET(hrc, pErrorInfo, + COMGETTER(Text)(bstrText.asOutParam()), hrc); + RTStrmPrintf(g_pStdErr, "%ls\n", bstrText.raw()); + + CHECK_ERROR2_RET(hrc, pErrorInfo, + COMGETTER(Next)(pErrorInfo.asOutParam()), hrc); + } + + return E_FAIL; + } + + + /* + * The machine seems to be ok, print its details. + */ + CloudMachineState_T enmState; + CHECK_ERROR2_RET(hrc, pMachine, + COMGETTER(State)(&enmState), + hrc); + switch (enmState) { + case CloudMachineState_Invalid: + RTPrintf(CloudMachine::tr("State: Invalid (%RU32)\n"), CloudMachineState_Invalid); + break; + + case CloudMachineState_Provisioning: + RTPrintf(CloudMachine::tr("State: Provisioning (%RU32)\n"), CloudMachineState_Provisioning); + break; + + case CloudMachineState_Running: + RTPrintf(CloudMachine::tr("State: Running (%RU32)\n"), CloudMachineState_Running); + break; + + case CloudMachineState_Starting: + RTPrintf(CloudMachine::tr("State: Starting (%RU32)\n"), CloudMachineState_Starting); + break; + + case CloudMachineState_Stopping: + RTPrintf(CloudMachine::tr("State: Stopping (%RU32)\n"), CloudMachineState_Stopping); + break; + + case CloudMachineState_Stopped: + RTPrintf(CloudMachine::tr("State: Stopped (%RU32)\n"), CloudMachineState_Stopped); + break; + + case CloudMachineState_CreatingImage: + RTPrintf(CloudMachine::tr("State: CreatingImage (%RU32)\n"), CloudMachineState_CreatingImage); + break; + + case CloudMachineState_Terminating: + RTPrintf(CloudMachine::tr("State: Terminating (%RU32)\n"), CloudMachineState_Terminating); + break; + + case CloudMachineState_Terminated: + RTPrintf(CloudMachine::tr("State: Terminated (%RU32)\n"), CloudMachineState_Terminated); + break; + + default: + RTPrintf(CloudMachine::tr("State: Unknown state (%RU32)\n"), enmState); + } + + ComPtr<IForm> pDetails; + CHECK_ERROR2_RET(hrc, pMachine, + GetDetailsForm(pDetails.asOutParam()), hrc); + + if (RT_UNLIKELY(pDetails.isNull())) + { + RTMsgError(CloudMachine::tr("null details")); /* better error message? */ + return E_FAIL; + } + + com::SafeIfaceArray<IFormValue> aValues; + CHECK_ERROR2_RET(hrc, pDetails, + COMGETTER(Values)(ComSafeArrayAsOutParam(aValues)), hrc); + for (size_t i = 0; i < aValues.size(); ++i) + { + hrc = printFormValue(aValues[i]); + if (FAILED(hrc)) + return hrc; + } + + return S_OK; +} + + +static HRESULT +printFormValue(const ComPtr<IFormValue> &pValue) +{ + HRESULT hrc; + + BOOL fVisible = FALSE; + CHECK_ERROR2_RET(hrc, pValue, + COMGETTER(Visible)(&fVisible), hrc); + if (!fVisible) + return S_OK; + + + com::Bstr bstrLabel; + CHECK_ERROR2_RET(hrc, pValue, + COMGETTER(Label)(bstrLabel.asOutParam()), hrc); + + FormValueType_T enmType; + CHECK_ERROR2_RET(hrc, pValue, + COMGETTER(Type)(&enmType), hrc); + + switch (enmType) + { + case FormValueType_Boolean: + { + ComPtr<IBooleanFormValue> pBoolValue; + hrc = pValue.queryInterfaceTo(pBoolValue.asOutParam()); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdErr, + CloudMachine::tr("%ls: unable to convert to boolean value\n"), + bstrLabel.raw()); + break; + } + + BOOL fSelected; + hrc = pBoolValue->GetSelected(&fSelected); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdOut, + "%ls: %Rhra", bstrLabel.raw(), hrc); + break; + } + + RTPrintf("%ls: %RTbool\n", + bstrLabel.raw(), RT_BOOL(fSelected)); + break; + } + + case FormValueType_String: + { + ComPtr<IStringFormValue> pStrValue; + hrc = pValue.queryInterfaceTo(pStrValue.asOutParam()); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdErr, + CloudMachine::tr("%ls: unable to convert to string value\n"), + bstrLabel.raw()); + break; + } + + /* + * GUI hack: if clipboard string is set, it contains + * untruncated long value, usually full OCID, so check it + * first. Make this selectable with an option? + */ + com::Bstr bstrValue; + hrc = pStrValue->COMGETTER(ClipboardString)(bstrValue.asOutParam()); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdOut, + "%ls: %Rhra", bstrLabel.raw(), hrc); + break; + } + + if (bstrValue.isEmpty()) + { + hrc = pStrValue->GetString(bstrValue.asOutParam()); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdOut, + "%ls: %Rhra", bstrLabel.raw(), hrc); + break; + } + } + + RTPrintf("%ls: %ls\n", + bstrLabel.raw(), bstrValue.raw()); + break; + } + + case FormValueType_RangedInteger: + { + ComPtr<IRangedIntegerFormValue> pIntValue; + hrc = pValue.queryInterfaceTo(pIntValue.asOutParam()); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdErr, + CloudMachine::tr("%ls: unable to convert to integer value\n"), + bstrLabel.raw()); + break; + } + + LONG lValue; + hrc = pIntValue->GetInteger(&lValue); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdOut, + "%ls: %Rhra", bstrLabel.raw(), hrc); + break; + } + + RTPrintf("%ls: %RI64\n", + bstrLabel.raw(), (int64_t)lValue); + break; + } + + case FormValueType_Choice: + { + ComPtr<IChoiceFormValue> pChoiceValue; + hrc = pValue.queryInterfaceTo(pChoiceValue.asOutParam()); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdErr, + CloudMachine::tr("%ls: unable to convert to choice value\n"), + bstrLabel.raw()); + break; + } + + com::SafeArray<BSTR> aValues; + hrc = pChoiceValue->COMGETTER(Values)(ComSafeArrayAsOutParam(aValues)); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdOut, + CloudMachine::tr("%ls: values: %Rhra"), + bstrLabel.raw(), hrc); + break; + } + + LONG idxSelected = -1; + hrc = pChoiceValue->GetSelectedIndex(&idxSelected); + if (FAILED(hrc)) + { + RTStrmPrintf(g_pStdOut, + CloudMachine::tr("%ls: selectedIndex: %Rhra"), + bstrLabel.raw(), hrc); + break; + } + + if (idxSelected < 0 || (size_t)idxSelected > aValues.size()) + { + RTStrmPrintf(g_pStdOut, + CloudMachine::tr("%ls: selected index %RI64 out of range [0, %zu)\n"), + bstrLabel.raw(), (int64_t)idxSelected, aValues.size()); + break; + } + + RTPrintf("%ls: %ls\n", + bstrLabel.raw(), aValues[idxSelected]); + break; + } + + default: + { + RTStrmPrintf(g_pStdOut, CloudMachine::tr("unknown value type %RU32\n"), enmType); + break; + } + } + + return S_OK; +} + + +/* + * Boilerplate code to get machine by name/id from the arguments. + * Shared by action subcommands b/c they currently don't have any + * extra options (but we can't use this for e.g. "info" that has + * --details). + */ +static RTEXITCODE +getMachineFromArgs(CMachineHandlerArg *a, int iFirst) +{ + static const RTGETOPTDEF s_aOptions[] = + { + CLOUD_MACHINE_RTGETOPTDEF_MACHINE, + CLOUD_MACHINE_RTGETOPTDEF_HELP + }; + + RTGETOPTSTATE OptState; + int vrc = RTGetOptInit(&OptState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), + iFirst, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + AssertRCReturn(vrc, RTMsgErrorExit(RTEXITCODE_INIT, /* internal error */ "RTGetOptInit: %Rra", vrc)); + + int ch; + RTGETOPTUNION Val; + while ((ch = RTGetOpt(&OptState, &Val)) != 0) + { + vrc = checkMachineSpecArgument(a, ch, Val); + if (vrc == VINF_SUCCESS) + continue; + if (vrc == VINF_CALLBACK_RETURN) + return RTEXITCODE_SUCCESS; + if (vrc == VERR_PARSE_ERROR) + return RTEXITCODE_SYNTAX; + + switch (ch) + { + /* no other options currently */ + default: + return RTGetOptPrintError(ch, &Val); + } + } + + HRESULT hrc = getMachineBySpec(a); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + return RTEXITCODE_SUCCESS; +} + + +/* + * cloud machine start "id" + */ +static RTEXITCODE +handleCloudMachineStart(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_START); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IProgress> pProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + PowerUp(pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress, SHOW_PROGRESS_NONE); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/* + * cloud machine reboot "id" + * "Press" ACPI power button, then power the instance back up. + */ +static RTEXITCODE +handleCloudMachineReboot(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_REBOOT); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IProgress> pProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + Reboot(pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress, SHOW_PROGRESS_NONE); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/* + * cloud machine reset "id" + * Force power down machine, then power the instance back up. + */ +static RTEXITCODE +handleCloudMachineReset(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_RESET); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IProgress> pProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + Reset(pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress, SHOW_PROGRESS_NONE); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/* + * cloud machine shutdown "id" + * "Press" ACPI power button. + */ +static RTEXITCODE +handleCloudMachineShutdown(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_SHUTDOWN); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IProgress> pProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + Shutdown(pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress, SHOW_PROGRESS_NONE); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/* + * cloud machine powerdown "id" + * Yank the power cord. + */ +static RTEXITCODE +handleCloudMachinePowerdown(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_POWERDOWN); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IProgress> pProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + PowerDown(pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress, SHOW_PROGRESS_NONE); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/* + * cloud machine terminate "id" + * Discard the instance running this machine. + */ +static RTEXITCODE +handleCloudMachineTerminate(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_TERMINATE); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IProgress> pProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + Terminate(pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress, SHOW_PROGRESS_NONE); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/* + * cloud machine console-history "id" + */ +static RTEXITCODE +handleCloudMachineConsoleHistory(CMachineHandlerArg *a, int iFirst) +{ + HRESULT hrc; + + // setCurrentSubcommand(HELP_SCOPE_CLOUD_MACHINE_CONSOLEHISTORY); + RTEXITCODE status = getMachineFromArgs(a, iFirst); + if (status != RTEXITCODE_SUCCESS) + return status; + + + ComPtr<IDataStream> pHistoryStream; + ComPtr<IProgress> pHistoryProgress; + CHECK_ERROR2_RET(hrc, a->pMachine, + GetConsoleHistory(pHistoryStream.asOutParam(), + pHistoryProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pHistoryProgress, SHOW_PROGRESS_NONE); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + bool fEOF = false; + while (!fEOF) + { + com::SafeArray<BYTE> aChunk; + CHECK_ERROR2_RET(hrc, pHistoryStream, + Read(64 *_1K, 0, ComSafeArrayAsOutParam(aChunk)), + RTEXITCODE_FAILURE); + if (aChunk.size() == 0) + break; + + RTStrmWrite(g_pStdOut, aChunk.raw(), aChunk.size()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp new file mode 100644 index 00000000..98a3f8f2 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp @@ -0,0 +1,2287 @@ +/* $Id: VBoxManageControlVM.cpp $ */ +/** @file + * VBoxManage - Implementation of the controlvm command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/ctype.h> +#include <iprt/getopt.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/thread.h> +#include <iprt/uuid.h> +#include <iprt/file.h> +#include <VBox/log.h> + +#include "VBoxManage.h" +#include "VBoxManageUtils.h" + +#include <list> + +DECLARE_TRANSLATION_CONTEXT(ControlVM); + +VMProcPriority_T nameToVMProcPriority(const char *pszName); + +/** + * Parses a number. + * + * @returns Valid number on success. + * @returns 0 if invalid number. All necessary bitching has been done. + * @param psz Pointer to the nic number. + */ +static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name) +{ + uint32_t u32; + char *pszNext; + int vrc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32); + if ( RT_SUCCESS(vrc) + && *pszNext == '\0' + && u32 >= 1 + && u32 <= cMaxNum) + return (unsigned)u32; + errorArgument(ControlVM::tr("Invalid %s number '%s'."), name, psz); + return 0; +} + +#define KBDCHARDEF_MOD_NONE 0x00 +#define KBDCHARDEF_MOD_SHIFT 0x01 + +typedef struct KBDCHARDEF +{ + uint8_t u8Scancode; + uint8_t u8Modifiers; +} KBDCHARDEF; + +static const KBDCHARDEF g_aASCIIChars[0x80] = +{ + /* 0x00 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x01 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x02 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x03 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x04 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x05 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x06 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x07 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x08 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x09 ' ' */ {0x0f, KBDCHARDEF_MOD_NONE}, + /* 0x0A ' ' */ {0x1c, KBDCHARDEF_MOD_NONE}, + /* 0x0B ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x0C ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x0D ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x0E ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x0F ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x10 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x11 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x12 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x13 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x14 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x15 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x16 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x17 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x18 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x19 ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x1A ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x1B ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x1C ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x1D ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x1E ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x1F ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, + /* 0x20 ' ' */ {0x39, KBDCHARDEF_MOD_NONE}, + /* 0x21 '!' */ {0x02, KBDCHARDEF_MOD_SHIFT}, + /* 0x22 '"' */ {0x28, KBDCHARDEF_MOD_SHIFT}, + /* 0x23 '#' */ {0x04, KBDCHARDEF_MOD_SHIFT}, + /* 0x24 '$' */ {0x05, KBDCHARDEF_MOD_SHIFT}, + /* 0x25 '%' */ {0x06, KBDCHARDEF_MOD_SHIFT}, + /* 0x26 '&' */ {0x08, KBDCHARDEF_MOD_SHIFT}, + /* 0x27 ''' */ {0x28, KBDCHARDEF_MOD_NONE}, + /* 0x28 '(' */ {0x0a, KBDCHARDEF_MOD_SHIFT}, + /* 0x29 ')' */ {0x0b, KBDCHARDEF_MOD_SHIFT}, + /* 0x2A '*' */ {0x09, KBDCHARDEF_MOD_SHIFT}, + /* 0x2B '+' */ {0x0d, KBDCHARDEF_MOD_SHIFT}, + /* 0x2C ',' */ {0x33, KBDCHARDEF_MOD_NONE}, + /* 0x2D '-' */ {0x0c, KBDCHARDEF_MOD_NONE}, + /* 0x2E '.' */ {0x34, KBDCHARDEF_MOD_NONE}, + /* 0x2F '/' */ {0x35, KBDCHARDEF_MOD_NONE}, + /* 0x30 '0' */ {0x0b, KBDCHARDEF_MOD_NONE}, + /* 0x31 '1' */ {0x02, KBDCHARDEF_MOD_NONE}, + /* 0x32 '2' */ {0x03, KBDCHARDEF_MOD_NONE}, + /* 0x33 '3' */ {0x04, KBDCHARDEF_MOD_NONE}, + /* 0x34 '4' */ {0x05, KBDCHARDEF_MOD_NONE}, + /* 0x35 '5' */ {0x06, KBDCHARDEF_MOD_NONE}, + /* 0x36 '6' */ {0x07, KBDCHARDEF_MOD_NONE}, + /* 0x37 '7' */ {0x08, KBDCHARDEF_MOD_NONE}, + /* 0x38 '8' */ {0x09, KBDCHARDEF_MOD_NONE}, + /* 0x39 '9' */ {0x0a, KBDCHARDEF_MOD_NONE}, + /* 0x3A ':' */ {0x27, KBDCHARDEF_MOD_SHIFT}, + /* 0x3B ';' */ {0x27, KBDCHARDEF_MOD_NONE}, + /* 0x3C '<' */ {0x33, KBDCHARDEF_MOD_SHIFT}, + /* 0x3D '=' */ {0x0d, KBDCHARDEF_MOD_NONE}, + /* 0x3E '>' */ {0x34, KBDCHARDEF_MOD_SHIFT}, + /* 0x3F '?' */ {0x35, KBDCHARDEF_MOD_SHIFT}, + /* 0x40 '@' */ {0x03, KBDCHARDEF_MOD_SHIFT}, + /* 0x41 'A' */ {0x1e, KBDCHARDEF_MOD_SHIFT}, + /* 0x42 'B' */ {0x30, KBDCHARDEF_MOD_SHIFT}, + /* 0x43 'C' */ {0x2e, KBDCHARDEF_MOD_SHIFT}, + /* 0x44 'D' */ {0x20, KBDCHARDEF_MOD_SHIFT}, + /* 0x45 'E' */ {0x12, KBDCHARDEF_MOD_SHIFT}, + /* 0x46 'F' */ {0x21, KBDCHARDEF_MOD_SHIFT}, + /* 0x47 'G' */ {0x22, KBDCHARDEF_MOD_SHIFT}, + /* 0x48 'H' */ {0x23, KBDCHARDEF_MOD_SHIFT}, + /* 0x49 'I' */ {0x17, KBDCHARDEF_MOD_SHIFT}, + /* 0x4A 'J' */ {0x24, KBDCHARDEF_MOD_SHIFT}, + /* 0x4B 'K' */ {0x25, KBDCHARDEF_MOD_SHIFT}, + /* 0x4C 'L' */ {0x26, KBDCHARDEF_MOD_SHIFT}, + /* 0x4D 'M' */ {0x32, KBDCHARDEF_MOD_SHIFT}, + /* 0x4E 'N' */ {0x31, KBDCHARDEF_MOD_SHIFT}, + /* 0x4F 'O' */ {0x18, KBDCHARDEF_MOD_SHIFT}, + /* 0x50 'P' */ {0x19, KBDCHARDEF_MOD_SHIFT}, + /* 0x51 'Q' */ {0x10, KBDCHARDEF_MOD_SHIFT}, + /* 0x52 'R' */ {0x13, KBDCHARDEF_MOD_SHIFT}, + /* 0x53 'S' */ {0x1f, KBDCHARDEF_MOD_SHIFT}, + /* 0x54 'T' */ {0x14, KBDCHARDEF_MOD_SHIFT}, + /* 0x55 'U' */ {0x16, KBDCHARDEF_MOD_SHIFT}, + /* 0x56 'V' */ {0x2f, KBDCHARDEF_MOD_SHIFT}, + /* 0x57 'W' */ {0x11, KBDCHARDEF_MOD_SHIFT}, + /* 0x58 'X' */ {0x2d, KBDCHARDEF_MOD_SHIFT}, + /* 0x59 'Y' */ {0x15, KBDCHARDEF_MOD_SHIFT}, + /* 0x5A 'Z' */ {0x2c, KBDCHARDEF_MOD_SHIFT}, + /* 0x5B '[' */ {0x1a, KBDCHARDEF_MOD_NONE}, + /* 0x5C '\' */ {0x2b, KBDCHARDEF_MOD_NONE}, + /* 0x5D ']' */ {0x1b, KBDCHARDEF_MOD_NONE}, + /* 0x5E '^' */ {0x07, KBDCHARDEF_MOD_SHIFT}, + /* 0x5F '_' */ {0x0c, KBDCHARDEF_MOD_SHIFT}, + /* 0x60 '`' */ {0x28, KBDCHARDEF_MOD_NONE}, + /* 0x61 'a' */ {0x1e, KBDCHARDEF_MOD_NONE}, + /* 0x62 'b' */ {0x30, KBDCHARDEF_MOD_NONE}, + /* 0x63 'c' */ {0x2e, KBDCHARDEF_MOD_NONE}, + /* 0x64 'd' */ {0x20, KBDCHARDEF_MOD_NONE}, + /* 0x65 'e' */ {0x12, KBDCHARDEF_MOD_NONE}, + /* 0x66 'f' */ {0x21, KBDCHARDEF_MOD_NONE}, + /* 0x67 'g' */ {0x22, KBDCHARDEF_MOD_NONE}, + /* 0x68 'h' */ {0x23, KBDCHARDEF_MOD_NONE}, + /* 0x69 'i' */ {0x17, KBDCHARDEF_MOD_NONE}, + /* 0x6A 'j' */ {0x24, KBDCHARDEF_MOD_NONE}, + /* 0x6B 'k' */ {0x25, KBDCHARDEF_MOD_NONE}, + /* 0x6C 'l' */ {0x26, KBDCHARDEF_MOD_NONE}, + /* 0x6D 'm' */ {0x32, KBDCHARDEF_MOD_NONE}, + /* 0x6E 'n' */ {0x31, KBDCHARDEF_MOD_NONE}, + /* 0x6F 'o' */ {0x18, KBDCHARDEF_MOD_NONE}, + /* 0x70 'p' */ {0x19, KBDCHARDEF_MOD_NONE}, + /* 0x71 'q' */ {0x10, KBDCHARDEF_MOD_NONE}, + /* 0x72 'r' */ {0x13, KBDCHARDEF_MOD_NONE}, + /* 0x73 's' */ {0x1f, KBDCHARDEF_MOD_NONE}, + /* 0x74 't' */ {0x14, KBDCHARDEF_MOD_NONE}, + /* 0x75 'u' */ {0x16, KBDCHARDEF_MOD_NONE}, + /* 0x76 'v' */ {0x2f, KBDCHARDEF_MOD_NONE}, + /* 0x77 'w' */ {0x11, KBDCHARDEF_MOD_NONE}, + /* 0x78 'x' */ {0x2d, KBDCHARDEF_MOD_NONE}, + /* 0x79 'y' */ {0x15, KBDCHARDEF_MOD_NONE}, + /* 0x7A 'z' */ {0x2c, KBDCHARDEF_MOD_NONE}, + /* 0x7B '{' */ {0x1a, KBDCHARDEF_MOD_SHIFT}, + /* 0x7C '|' */ {0x2b, KBDCHARDEF_MOD_SHIFT}, + /* 0x7D '}' */ {0x1b, KBDCHARDEF_MOD_SHIFT}, + /* 0x7E '~' */ {0x29, KBDCHARDEF_MOD_SHIFT}, + /* 0x7F ' ' */ {0x00, KBDCHARDEF_MOD_NONE}, +}; + +static HRESULT keyboardPutScancodes(IKeyboard *pKeyboard, const std::list<LONG> &llScancodes) +{ + /* Send scancodes to the VM. */ + com::SafeArray<LONG> saScancodes(llScancodes); + + HRESULT hrc = S_OK; + size_t i; + for (i = 0; i < saScancodes.size(); ++i) + { + hrc = pKeyboard->PutScancode(saScancodes[i]); + if (FAILED(hrc)) + { + RTMsgError(ControlVM::tr("Failed to send a scancode.")); + break; + } + + RTThreadSleep(10); /* "Typing" too fast causes lost characters. */ + } + + return hrc; +} + +static void keyboardCharsToScancodes(const char *pch, size_t cchMax, std::list<LONG> &llScancodes, bool *pfShift) +{ + size_t cchProcessed = 0; + const char *p = pch; + while (cchProcessed < cchMax) + { + ++cchProcessed; + const uint8_t c = (uint8_t)*p++; + if (c < RT_ELEMENTS(g_aASCIIChars)) + { + const KBDCHARDEF *d = &g_aASCIIChars[c]; + if (d->u8Scancode) + { + const bool fNeedShift = RT_BOOL(d->u8Modifiers & KBDCHARDEF_MOD_SHIFT); + if (*pfShift != fNeedShift) + { + *pfShift = fNeedShift; + /* Press or release the SHIFT key. */ + llScancodes.push_back(0x2a | (fNeedShift? 0x00: 0x80)); + } + + llScancodes.push_back(d->u8Scancode); + llScancodes.push_back(d->u8Scancode | 0x80); + } + } + } +} + +static HRESULT keyboardPutString(IKeyboard *pKeyboard, int argc, char **argv) +{ + std::list<LONG> llScancodes; + bool fShift = false; + + /* Convert command line string(s) to the en-us keyboard scancodes. */ + int i; + for (i = 1 + 1; i < argc; ++i) + { + if (!llScancodes.empty()) + { + /* Insert a SPACE before the next string. */ + llScancodes.push_back(0x39); + llScancodes.push_back(0x39 | 0x80); + } + + keyboardCharsToScancodes(argv[i], strlen(argv[i]), llScancodes, &fShift); + } + + /* Release SHIFT if pressed. */ + if (fShift) + llScancodes.push_back(0x2a | 0x80); + + return keyboardPutScancodes(pKeyboard, llScancodes); +} + +static HRESULT keyboardPutFile(IKeyboard *pKeyboard, const char *pszFilename) +{ + std::list<LONG> llScancodes; + bool fShift = false; + + RTFILE File = NIL_RTFILE; + int vrc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_SUCCESS(vrc)) + { + uint64_t cbFile = 0; + vrc = RTFileQuerySize(File, &cbFile); + if (RT_SUCCESS(vrc)) + { + const uint64_t cbFileMax = _64K; + if (cbFile <= cbFileMax) + { + const size_t cbBuffer = _4K; + char *pchBuf = (char *)RTMemAlloc(cbBuffer); + if (pchBuf) + { + size_t cbRemaining = (size_t)cbFile; + while (cbRemaining > 0) + { + const size_t cbToRead = cbRemaining > cbBuffer ? cbBuffer : cbRemaining; + + size_t cbRead = 0; + vrc = RTFileRead(File, pchBuf, cbToRead, &cbRead); + if (RT_FAILURE(vrc) || cbRead == 0) + break; + + keyboardCharsToScancodes(pchBuf, cbRead, llScancodes, &fShift); + cbRemaining -= cbRead; + } + + RTMemFree(pchBuf); + } + else + RTMsgError(ControlVM::tr("Out of memory allocating %d bytes.", "", cbBuffer), cbBuffer); + } + else + RTMsgError(ControlVM::tr("File size %RI64 is greater than %RI64: '%s'."), cbFile, cbFileMax, pszFilename); + } + else + RTMsgError(ControlVM::tr("Cannot get size of file '%s': %Rrc."), pszFilename, vrc); + + RTFileClose(File); + } + else + RTMsgError(ControlVM::tr("Cannot open file '%s': %Rrc."), pszFilename, vrc); + + /* Release SHIFT if pressed. */ + if (fShift) + llScancodes.push_back(0x2a | 0x80); + + return keyboardPutScancodes(pKeyboard, llScancodes); +} + + +RTEXITCODE handleControlVM(HandlerArg *a) +{ + using namespace com; + bool fNeedsSaving = false; + HRESULT hrc; + + if (a->argc < 2) + return errorSyntax(ControlVM::tr("Not enough parameters.")); + + /* try to find the given machine */ + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + /* open a session for the VM */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + + ComPtr<IConsole> console; + ComPtr<IMachine> sessionMachine; + + do + { + /* get the associated console */ + CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam())); + if (!console) + return RTMsgErrorExit(RTEXITCODE_FAILURE, ControlVM::tr("Machine '%s' is not currently running."), a->argv[0]); + + /* ... and session machine */ + CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam())); + + /* which command? */ + if (!strcmp(a->argv[1], "pause")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_PAUSE); + CHECK_ERROR_BREAK(console, Pause()); + } + else if (!strcmp(a->argv[1], "resume")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RESUME); + CHECK_ERROR_BREAK(console, Resume()); + } + else if (!strcmp(a->argv[1], "reset")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RESET); + CHECK_ERROR_BREAK(console, Reset()); + } + else if (!strcmp(a->argv[1], "unplugcpu")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_UNPLUGCPU); + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + unsigned n = parseNum(a->argv[2], 32, "CPU"); + + CHECK_ERROR_BREAK(sessionMachine, HotUnplugCPU(n)); + } + else if (!strcmp(a->argv[1], "plugcpu")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_PLUGCPU); + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + unsigned n = parseNum(a->argv[2], 32, "CPU"); + + CHECK_ERROR_BREAK(sessionMachine, HotPlugCPU(n)); + } + else if (!strcmp(a->argv[1], "cpuexecutioncap")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_CPUEXECUTIONCAP); + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + unsigned n = parseNum(a->argv[2], 100, "ExecutionCap"); + + CHECK_ERROR_BREAK(sessionMachine, COMSETTER(CPUExecutionCap)(n)); + } + else if (!strcmp(a->argv[1], "audioin")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_AUDIOIN); + + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> adapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(adapter.asOutParam())); + if (adapter) + { + bool fEnabled; + if (RT_FAILURE(parseBool(a->argv[2], &fEnabled))) + { + errorSyntax(ControlVM::tr("Invalid value '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(EnabledIn)(fEnabled), RTEXITCODE_FAILURE); + fNeedsSaving = true; + } + else + { + errorSyntax(ControlVM::tr("Audio adapter not enabled in VM configuration.")); + hrc = E_FAIL; + break; + } + } + else if (!strcmp(a->argv[1], "audioout")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_AUDIOOUT); + + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> adapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(adapter.asOutParam())); + if (adapter) + { + bool fEnabled; + if (RT_FAILURE(parseBool(a->argv[2], &fEnabled))) + { + errorSyntax(ControlVM::tr("Invalid value '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(EnabledOut)(fEnabled), RTEXITCODE_FAILURE); + fNeedsSaving = true; + } + else + { + errorSyntax(ControlVM::tr("Audio adapter not enabled in VM configuration.")); + hrc = E_FAIL; + break; + } + } +#ifdef VBOX_WITH_SHARED_CLIPBOARD + else if (!strcmp(a->argv[1], "clipboard")) + { + if (a->argc <= 1 + 1) + { + errorArgument(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + ClipboardMode_T mode = ClipboardMode_Disabled; /* Shut up MSC */ + if (!strcmp(a->argv[2], "mode")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_CLIPBOARD_MODE); + if (a->argc <= 1 + 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s %s'."), a->argv[1], a->argv[2]); + hrc = E_FAIL; + break; + } + + if (!strcmp(a->argv[3], "disabled")) + mode = ClipboardMode_Disabled; + else if (!strcmp(a->argv[3], "hosttoguest")) + mode = ClipboardMode_HostToGuest; + else if (!strcmp(a->argv[3], "guesttohost")) + mode = ClipboardMode_GuestToHost; + else if (!strcmp(a->argv[3], "bidirectional")) + mode = ClipboardMode_Bidirectional; + else + { + errorSyntax(ControlVM::tr("Invalid '%s %s' argument '%s'."), a->argv[1], a->argv[2], a->argv[3]); + hrc = E_FAIL; + break; + } + + CHECK_ERROR_BREAK(sessionMachine, COMSETTER(ClipboardMode)(mode)); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } +# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS + else if (!strcmp(a->argv[2], "filetransfers")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_CLIPBOARD_FILETRANSFERS); + if (a->argc <= 1 + 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s %s'."), a->argv[1], a->argv[2]); + hrc = E_FAIL; + break; + } + + bool fEnabled; + if (RT_FAILURE(parseBool(a->argv[3], &fEnabled))) + { + errorSyntax(ControlVM::tr("Invalid '%s %s' argument '%s'."), a->argv[1], a->argv[2], a->argv[3]); + hrc = E_FAIL; + break; + } + + CHECK_ERROR_BREAK(sessionMachine, COMSETTER(ClipboardFileTransfersEnabled)(fEnabled)); + fNeedsSaving = true; + } +# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ + else + { + errorArgument(ControlVM::tr("Invalid '%s' argument '%s'."), a->argv[1], a->argv[2]); + hrc = E_FAIL; + break; + } + } +#endif /* VBOX_WITH_SHARED_CLIPBOARD */ + else if (!strcmp(a->argv[1], "draganddrop")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_DRAGANDDROP); + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + DnDMode_T mode = DnDMode_Disabled; /* Shup up MSC. */ + if (!strcmp(a->argv[2], "disabled")) + mode = DnDMode_Disabled; + else if (!strcmp(a->argv[2], "hosttoguest")) + mode = DnDMode_HostToGuest; + else if (!strcmp(a->argv[2], "guesttohost")) + mode = DnDMode_GuestToHost; + else if (!strcmp(a->argv[2], "bidirectional")) + mode = DnDMode_Bidirectional; + else + { + errorSyntax(ControlVM::tr("Invalid '%s' argument '%s'."), a->argv[1], a->argv[2]); + hrc = E_FAIL; + } + if (SUCCEEDED(hrc)) + { + CHECK_ERROR_BREAK(sessionMachine, COMSETTER(DnDMode)(mode)); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + } + else if (!strcmp(a->argv[1], "poweroff")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_POWEROFF); + ComPtr<IProgress> progress; + CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam())); + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR(progress, (ControlVM::tr("Failed to power off machine."))); + } + else if (!strcmp(a->argv[1], "savestate")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SAVESTATE); + /* first pause so we don't trigger a live save which needs more time/resources */ + bool fPaused = false; + hrc = console->Pause(); + if (FAILED(hrc)) + { + bool fError = true; + if (hrc == VBOX_E_INVALID_VM_STATE) + { + /* check if we are already paused */ + MachineState_T machineState; + CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState)); + /* the error code was lost by the previous instruction */ + hrc = VBOX_E_INVALID_VM_STATE; + if (machineState != MachineState_Paused) + { + RTMsgError(ControlVM::tr("Machine in invalid state %d -- %s."), + machineState, machineStateToName(machineState, false)); + } + else + { + fError = false; + fPaused = true; + } + } + if (fError) + break; + } + + ComPtr<IProgress> progress; + CHECK_ERROR(sessionMachine, SaveState(progress.asOutParam())); + if (FAILED(hrc)) + { + if (!fPaused) + console->Resume(); + break; + } + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR(progress, (ControlVM::tr("Failed to save machine state."))); + if (FAILED(hrc)) + { + if (!fPaused) + console->Resume(); + } + } + else if (!strcmp(a->argv[1], "acpipowerbutton")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_ACPIPOWERBUTTON); + CHECK_ERROR_BREAK(console, PowerButton()); + } + else if (!strcmp(a->argv[1], "acpisleepbutton")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_ACPISLEEPBUTTON); + CHECK_ERROR_BREAK(console, SleepButton()); + } +#ifdef VBOX_WITH_GUEST_CONTROL + else if ( !strcmp(a->argv[1], "reboot") + || !strcmp(a->argv[1], "shutdown")) /* With shutdown we mean gracefully powering off the VM by letting the guest OS do its thing. */ + { + const bool fReboot = !strcmp(a->argv[1], "reboot"); + if (fReboot) + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_REBOOT); + else + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SHUTDOWN); + + ComPtr<IGuest> pGuest; + CHECK_ERROR_BREAK(console, COMGETTER(Guest)(pGuest.asOutParam())); + if (!pGuest) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + + com::SafeArray<GuestShutdownFlag_T> aShutdownFlags; + if (fReboot) + aShutdownFlags.push_back(GuestShutdownFlag_Reboot); + else + aShutdownFlags.push_back(GuestShutdownFlag_PowerOff); + + if ( a->argc >= 3 + && !strcmp(a->argv[2], "--force")) + aShutdownFlags.push_back(GuestShutdownFlag_Force); + + CHECK_ERROR(pGuest, Shutdown(ComSafeArrayAsInParam(aShutdownFlags))); + if (FAILED(hrc)) + { + if (hrc == VBOX_E_NOT_SUPPORTED) + { + if (fReboot) + RTMsgError(ControlVM::tr("Current installed Guest Additions don't support rebooting the guest.")); + else + RTMsgError(ControlVM::tr("Current installed Guest Additions don't support shutting down the guest.")); + } + } + } +#endif + else if (!strcmp(a->argv[1], "keyboardputscancode")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_KEYBOARDPUTSCANCODE); + ComPtr<IKeyboard> pKeyboard; + CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(pKeyboard.asOutParam())); + if (!pKeyboard) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s)."), + a->argv[1]); + hrc = E_FAIL; + break; + } + + std::list<LONG> llScancodes; + + /* Process the command line. */ + int i; + for (i = 1 + 1; i < a->argc; i++) + { + if ( RT_C_IS_XDIGIT (a->argv[i][0]) + && RT_C_IS_XDIGIT (a->argv[i][1]) + && a->argv[i][2] == 0) + { + uint8_t u8Scancode; + int vrc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode); + if (RT_FAILURE (vrc)) + { + RTMsgError(ControlVM::tr("Converting '%s' returned %Rrc!"), a->argv[i], vrc); + hrc = E_FAIL; + break; + } + + llScancodes.push_back(u8Scancode); + } + else + { + RTMsgError(ControlVM::tr("'%s' is not a hex byte!"), a->argv[i]); + hrc = E_FAIL; + break; + } + } + + if (FAILED(hrc)) + break; + + hrc = keyboardPutScancodes(pKeyboard, llScancodes); + } + else if (!strcmp(a->argv[1], "keyboardputstring")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_KEYBOARDPUTSTRING); + ComPtr<IKeyboard> pKeyboard; + CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(pKeyboard.asOutParam())); + if (!pKeyboard) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'. Expected ASCII string(s)."), a->argv[1]); + hrc = E_FAIL; + break; + } + + hrc = keyboardPutString(pKeyboard, a->argc, a->argv); + } + else if (!strcmp(a->argv[1], "keyboardputfile")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_KEYBOARDPUTFILE); + ComPtr<IKeyboard> pKeyboard; + CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(pKeyboard.asOutParam())); + if (!pKeyboard) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + hrc = keyboardPutFile(pKeyboard, a->argv[2]); + } + else if (!strncmp(a->argv[1], "setlinkstate", 12)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SETLINKSTATE); + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (adapter) + { + bool fEnabled; + if (RT_FAILURE(parseBool(a->argv[2], &fEnabled))) + { + errorSyntax(ControlVM::tr("Invalid link state '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(fEnabled)); + fNeedsSaving = true; + } + } + /* here the order in which strncmp is called is important + * cause nictracefile can be very well compared with + * nictrace and nic and thus everything will always fail + * if the order is changed + */ + else if (!strncmp(a->argv[1], "nictracefile", 12)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NICTRACEFILE); + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (adapter) + { + BOOL fEnabled; + adapter->COMGETTER(Enabled)(&fEnabled); + if (fEnabled) + { + if (a->argv[2]) + { + CHECK_ERROR_RET(adapter, COMSETTER(TraceFile)(Bstr(a->argv[2]).raw()), RTEXITCODE_FAILURE); + } + else + { + errorSyntax(ControlVM::tr("Filename not specified for NIC %lu."), n); + hrc = E_FAIL; + break; + } + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + else + RTMsgError(ControlVM::tr("The NIC %d is currently disabled and thus its tracefile can't be changed."), n); + } + } + else if (!strncmp(a->argv[1], "nictrace", 8)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NICTRACE); + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][8], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (adapter) + { + BOOL fEnabled; + adapter->COMGETTER(Enabled)(&fEnabled); + if (fEnabled) + { + bool fTraceEnabled; + if (RT_FAILURE(parseBool(a->argv[2], &fTraceEnabled))) + { + errorSyntax(ControlVM::tr("Invalid nictrace%lu argument '%s'."), n, a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(fTraceEnabled), RTEXITCODE_FAILURE); + fNeedsSaving = true; + } + else + RTMsgError(ControlVM::tr("The NIC %d is currently disabled and thus its trace flag can't be changed."), n); + } + } + else if( a->argc > 2 + && !strncmp(a->argv[1], "natpf", 5)) + { + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][5], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 2) + { + errorArgument(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (!adapter) + { + hrc = E_FAIL; + break; + } + ComPtr<INATEngine> engine; + CHECK_ERROR(adapter, COMGETTER(NATEngine)(engine.asOutParam())); + if (!engine) + { + hrc = E_FAIL; + break; + } + + if (!strcmp(a->argv[2], "delete")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NATPF_DELETE); + if (a->argc >= 3) + CHECK_ERROR(engine, RemoveRedirect(Bstr(a->argv[3]).raw())); + } + else + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NATPF); +#define ITERATE_TO_NEXT_TERM(ch) \ + do { \ + while (*ch != ',') \ + { \ + if (*ch == 0) \ + { \ + return errorSyntax(ControlVM::tr("Missing or invalid argument to '%s'."), \ + a->argv[1]); \ + } \ + ch++; \ + } \ + *ch = '\0'; \ + ch++; \ + } while(0) + + char *strName; + char *strProto; + char *strHostIp; + char *strHostPort; + char *strGuestIp; + char *strGuestPort; + char *strRaw = RTStrDup(a->argv[2]); + char *ch = strRaw; + strName = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strProto = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strHostIp = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strHostPort = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strGuestIp = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strGuestPort = RTStrStrip(ch); + NATProtocol_T proto; + if (RTStrICmp(strProto, "udp") == 0) + proto = NATProtocol_UDP; + else if (RTStrICmp(strProto, "tcp") == 0) + proto = NATProtocol_TCP; + else + { + return errorSyntax(ControlVM::tr("Wrong rule proto '%s' specified -- only 'udp' and 'tcp' are allowed."), + strProto); + } + CHECK_ERROR(engine, AddRedirect(Bstr(strName).raw(), proto, Bstr(strHostIp).raw(), + RTStrToUInt16(strHostPort), Bstr(strGuestIp).raw(), RTStrToUInt16(strGuestPort))); +#undef ITERATE_TO_NEXT_TERM + } + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + else if (!strncmp(a->argv[1], "nicproperty", 11)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NICPROPERTY); + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][11], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (adapter) + { + BOOL fEnabled; + adapter->COMGETTER(Enabled)(&fEnabled); + if (fEnabled) + { + /* Parse 'name=value' */ + char *pszProperty = RTStrDup(a->argv[2]); + if (pszProperty) + { + char *pDelimiter = strchr(pszProperty, '='); + if (pDelimiter) + { + *pDelimiter = '\0'; + + Bstr bstrName = pszProperty; + Bstr bstrValue = &pDelimiter[1]; + CHECK_ERROR(adapter, SetProperty(bstrName.raw(), bstrValue.raw())); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + else + { + errorSyntax(ControlVM::tr("Invalid nicproperty%d argument '%s'."), n, a->argv[2]); + hrc = E_FAIL; + } + RTStrFree(pszProperty); + } + else + { + RTMsgError(ControlVM::tr("Failed to allocate memory for nicproperty%d '%s'."), + n, a->argv[2]); + hrc = E_FAIL; + } + if (FAILED(hrc)) + break; + } + else + RTMsgError(ControlVM::tr("The NIC %d is currently disabled and thus its properties can't be changed."), n); + } + } + else if (!strncmp(a->argv[1], "nicpromisc", 10)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NICPROMISC); + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][10], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (adapter) + { + BOOL fEnabled; + adapter->COMGETTER(Enabled)(&fEnabled); + if (fEnabled) + { + NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy; + if (!strcmp(a->argv[2], "deny")) + enmPromiscModePolicy = NetworkAdapterPromiscModePolicy_Deny; + else if ( !strcmp(a->argv[2], "allow-vms") + || !strcmp(a->argv[2], "allow-network")) + enmPromiscModePolicy = NetworkAdapterPromiscModePolicy_AllowNetwork; + else if (!strcmp(a->argv[2], "allow-all")) + enmPromiscModePolicy = NetworkAdapterPromiscModePolicy_AllowAll; + else + { + errorSyntax(ControlVM::tr("Unknown promiscuous mode policy '%s'."), a->argv[2]); + hrc = E_INVALIDARG; + break; + } + + CHECK_ERROR(adapter, COMSETTER(PromiscModePolicy)(enmPromiscModePolicy)); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + else + RTMsgError(ControlVM::tr("The NIC %d is currently disabled and thus its promiscuous mode can't be changed."), n); + } + } + else if (!strncmp(a->argv[1], "nic", 3)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_NIC); + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, sessionMachine); + unsigned n = parseNum(&a->argv[1][3], NetworkAdapterCount, "NIC"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc <= 2) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + /* get the corresponding network adapter */ + ComPtr<INetworkAdapter> adapter; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam())); + if (adapter) + { + BOOL fEnabled; + adapter->COMGETTER(Enabled)(&fEnabled); + if (fEnabled) + { + if (!strcmp(a->argv[2], "null")) + { + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_Null), RTEXITCODE_FAILURE); + } + else if (!strcmp(a->argv[2], "nat")) + { + if (a->argc == 4) + CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3]).raw()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_NAT), RTEXITCODE_FAILURE); + } + else if ( !strcmp(a->argv[2], "bridged") + || !strcmp(a->argv[2], "hostif")) /* backward compatibility */ + { + if (a->argc <= 3) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(BridgedInterface)(Bstr(a->argv[3]).raw()), RTEXITCODE_FAILURE); + verifyHostNetworkInterfaceName(a->virtualBox, a->argv[3], HostNetworkInterfaceType_Bridged); + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_Bridged), RTEXITCODE_FAILURE); + } + else if (!strcmp(a->argv[2], "intnet")) + { + if (a->argc <= 3) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(InternalNetwork)(Bstr(a->argv[3]).raw()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_Internal), RTEXITCODE_FAILURE); + } +#if defined(VBOX_WITH_NETFLT) + else if (!strcmp(a->argv[2], "hostonly")) + { + if (a->argc <= 3) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(HostOnlyInterface)(Bstr(a->argv[3]).raw()), RTEXITCODE_FAILURE); + verifyHostNetworkInterfaceName(a->virtualBox, a->argv[3], HostNetworkInterfaceType_HostOnly); + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_HostOnly), RTEXITCODE_FAILURE); + } +#endif + else if (!strcmp(a->argv[2], "generic")) + { + if (a->argc <= 3) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(GenericDriver)(Bstr(a->argv[3]).raw()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_Generic), RTEXITCODE_FAILURE); + } + else if (!strcmp(a->argv[2], "natnetwork")) + { + if (a->argc <= 3) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3]).raw()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(adapter, COMSETTER(AttachmentType)(NetworkAttachmentType_NATNetwork), RTEXITCODE_FAILURE); + } + else + { + errorSyntax(ControlVM::tr("Invalid type '%s' specfied for NIC %lu."), a->argv[2], n); + hrc = E_FAIL; + break; + } + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + else + RTMsgError(ControlVM::tr("The NIC %d is currently disabled and thus its attachment type can't be changed."), n); + } + } + else if ( !strcmp(a->argv[1], "vrde") + || !strcmp(a->argv[1], "vrdp")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_VRDE); + if (!strcmp(a->argv[1], "vrdp")) + RTMsgWarning(ControlVM::tr("'vrdp' is deprecated. Use 'vrde'.")); + + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + if (vrdeServer) + { + bool fEnabled; + if (RT_FAILURE(parseBool(a->argv[2], &fEnabled))) + { + errorSyntax(ControlVM::tr("Invalid remote desktop server state '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR_BREAK(vrdeServer, COMSETTER(Enabled)(fEnabled)); + fNeedsSaving = true; + } + } + else if ( !strcmp(a->argv[1], "vrdeport") + || !strcmp(a->argv[1], "vrdpport")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_VRDEPORT); + if (!strcmp(a->argv[1], "vrdpport")) + RTMsgWarning(ControlVM::tr("'vrdpport' is deprecated. Use 'vrdeport'.")); + + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + if (vrdeServer) + { + Bstr ports; + + if (!strcmp(a->argv[2], "default")) + ports = "0"; + else + ports = a->argv[2]; + + CHECK_ERROR_BREAK(vrdeServer, SetVRDEProperty(Bstr("TCP/Ports").raw(), ports.raw())); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + } + else if ( !strcmp(a->argv[1], "vrdevideochannelquality") + || !strcmp(a->argv[1], "vrdpvideochannelquality")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_VRDEVIDEOCHANNELQUALITY); + if (!strcmp(a->argv[1], "vrdpvideochannelquality")) + RTMsgWarning(ControlVM::tr("'vrdpvideochannelquality' is deprecated. Use 'vrdevideochannelquality'.")); + + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + if (vrdeServer) + { + Bstr value = a->argv[2]; + + CHECK_ERROR(vrdeServer, SetVRDEProperty(Bstr("VideoChannel/Quality").raw(), value.raw())); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + } + else if (!strcmp(a->argv[1], "vrdeproperty")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_VRDEPROPERTY); + if (a->argc <= 1 + 1) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + if (vrdeServer) + { + /* Parse 'name=value' */ + char *pszProperty = RTStrDup(a->argv[2]); + if (pszProperty) + { + char *pDelimiter = strchr(pszProperty, '='); + if (pDelimiter) + { + *pDelimiter = '\0'; + + Bstr bstrName = pszProperty; + Bstr bstrValue = &pDelimiter[1]; + CHECK_ERROR(vrdeServer, SetVRDEProperty(bstrName.raw(), bstrValue.raw())); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + } + else + { + errorSyntax(ControlVM::tr("Invalid vrdeproperty argument '%s'."), a->argv[2]); + hrc = E_FAIL; + } + RTStrFree(pszProperty); + } + else + { + RTMsgError(ControlVM::tr("Failed to allocate memory for VRDE property '%s'."), + a->argv[2]); + hrc = E_FAIL; + } + } + if (FAILED(hrc)) + { + break; + } + } + else if ( !strcmp(a->argv[1], "usbattach") + || !strcmp(a->argv[1], "usbdetach")) + { + bool attach = !strcmp(a->argv[1], "usbattach"); + if (attach) + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_USBATTACH); + else + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_USBDETACH); + + if (a->argc < 3) + { + errorSyntax(ControlVM::tr("Not enough parameters.")); + hrc = E_FAIL; + break; + } + else if (a->argc == 4 || a->argc > 5) + { + errorSyntax(ControlVM::tr("Wrong number of arguments.")); + hrc = E_FAIL; + break; + } + + Bstr usbId = a->argv[2]; + Bstr captureFilename; + + if (a->argc == 5) + { + if (!strcmp(a->argv[3], "--capturefile")) + captureFilename = a->argv[4]; + else + { + errorSyntax(ControlVM::tr("Invalid parameter '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + } + + Guid guid(usbId); + if (!guid.isValid()) + { + // assume address + if (attach) + { + ComPtr<IHost> host; + CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(Host)(host.asOutParam())); + SafeIfaceArray <IHostUSBDevice> coll; + CHECK_ERROR_BREAK(host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll))); + ComPtr<IHostUSBDevice> dev; + CHECK_ERROR_BREAK(host, FindUSBDeviceByAddress(Bstr(a->argv[2]).raw(), + dev.asOutParam())); + CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam())); + } + else + { + SafeIfaceArray <IUSBDevice> coll; + CHECK_ERROR_BREAK(console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll))); + ComPtr<IUSBDevice> dev; + CHECK_ERROR_BREAK(console, FindUSBDeviceByAddress(Bstr(a->argv[2]).raw(), + dev.asOutParam())); + CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam())); + } + } + else if (guid.isZero()) + { + errorSyntax(ControlVM::tr("Zero UUID argument '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + + if (attach) + CHECK_ERROR_BREAK(console, AttachUSBDevice(usbId.raw(), captureFilename.raw())); + else + { + ComPtr<IUSBDevice> dev; + CHECK_ERROR_BREAK(console, DetachUSBDevice(usbId.raw(), + dev.asOutParam())); + } + } + else if (!strcmp(a->argv[1], "setvideomodehint")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SETVIDEOMODEHINT); + if (a->argc != 5 && a->argc != 6 && a->argc != 7 && a->argc != 9) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + bool fEnabled = true; + uint32_t uXRes = RTStrToUInt32(a->argv[2]); + uint32_t uYRes = RTStrToUInt32(a->argv[3]); + uint32_t uBpp = RTStrToUInt32(a->argv[4]); + uint32_t uDisplayIdx = 0; + bool fChangeOrigin = false; + int32_t iOriginX = 0; + int32_t iOriginY = 0; + if (a->argc >= 6) + uDisplayIdx = RTStrToUInt32(a->argv[5]); + if (a->argc >= 7) + { + if (RT_FAILURE(parseBool(a->argv[6], &fEnabled))) + { + errorSyntax(ControlVM::tr("Either \"yes\" or \"no\" is expected.")); + hrc = E_FAIL; + break; + } + } + if (a->argc == 9) + { + iOriginX = RTStrToInt32(a->argv[7]); + iOriginY = RTStrToInt32(a->argv[8]); + fChangeOrigin = true; + } + + ComPtr<IDisplay> pDisplay; + CHECK_ERROR_BREAK(console, COMGETTER(Display)(pDisplay.asOutParam())); + if (!pDisplay) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + CHECK_ERROR_BREAK(pDisplay, SetVideoModeHint(uDisplayIdx, fEnabled, + fChangeOrigin, iOriginX, iOriginY, + uXRes, uYRes, uBpp, true)); + } + else if (!strcmp(a->argv[1], "setscreenlayout")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SETSCREENLAYOUT); + if (a->argc < 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + ComPtr<IDisplay> pDisplay; + CHECK_ERROR_BREAK(console, COMGETTER(Display)(pDisplay.asOutParam())); + if (!pDisplay) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + + com::SafeIfaceArray<IGuestScreenInfo> aGuestScreenInfos; + + /* Parse "<display> on|primary <xorigin> <yorigin> <xres> <yres> <bpp> | off" sequences. */ + int argc = a->argc - 2; + char **argv = &a->argv[2]; + while (argc >= 2) + { + ULONG aDisplay = RTStrToUInt32(argv[0]); + BOOL aPrimary = FALSE; + + GuestMonitorStatus_T aStatus; + if (RTStrICmp(argv[1], "primary") == 0) + { + aStatus = GuestMonitorStatus_Enabled; + aPrimary = TRUE; + } + else if (RTStrICmp(argv[1], "on") == 0) + aStatus = GuestMonitorStatus_Enabled; + else if (RTStrICmp(argv[1], "off") == 0) + aStatus = GuestMonitorStatus_Disabled; + else + { + errorSyntax(ControlVM::tr("Display status must be <on> or <off>.")); + hrc = E_FAIL; + break; + } + + BOOL aChangeOrigin = FALSE; + LONG aOriginX = 0; + LONG aOriginY = 0; + ULONG aWidth = 0; + ULONG aHeight = 0; + ULONG aBitsPerPixel = 0; + if (aStatus == GuestMonitorStatus_Enabled) + { + if (argc < 7) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + aChangeOrigin = TRUE; + aOriginX = RTStrToUInt32(argv[2]); + aOriginY = RTStrToUInt32(argv[3]); + aWidth = RTStrToUInt32(argv[4]); + aHeight = RTStrToUInt32(argv[5]); + aBitsPerPixel = RTStrToUInt32(argv[6]); + + argc -= 7; + argv += 7; + } + else + { + argc -= 2; + argv += 2; + } + + ComPtr<IGuestScreenInfo> pInfo; + CHECK_ERROR_BREAK(pDisplay, CreateGuestScreenInfo(aDisplay, aStatus, aPrimary, aChangeOrigin, + aOriginX, aOriginY, aWidth, aHeight, aBitsPerPixel, + pInfo.asOutParam())); + aGuestScreenInfos.push_back(pInfo); + } + + if (FAILED(hrc)) + break; + + CHECK_ERROR_BREAK(pDisplay, SetScreenLayout(ScreenLayoutMode_Apply, ComSafeArrayAsInParam(aGuestScreenInfos))); + } + else if (!strcmp(a->argv[1], "setcredentials")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SETCREDENTIALS); + bool fAllowLocalLogon = true; + if ( a->argc == 7 + || ( a->argc == 8 + && ( !strcmp(a->argv[3], "-p") + || !strcmp(a->argv[3], "--passwordfile")))) + { + if ( strcmp(a->argv[5 + (a->argc - 7)], "--allowlocallogon") + && strcmp(a->argv[5 + (a->argc - 7)], "-allowlocallogon")) + { + errorSyntax(ControlVM::tr("Invalid parameter '%s'."), a->argv[5]); + hrc = E_FAIL; + break; + } + if (!strcmp(a->argv[6 + (a->argc - 7)], "no")) + fAllowLocalLogon = false; + } + else if ( a->argc != 5 + && ( a->argc != 6 + || ( strcmp(a->argv[3], "-p") + && strcmp(a->argv[3], "--passwordfile")))) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + Utf8Str passwd, domain; + if (a->argc == 5 || a->argc == 7) + { + passwd = a->argv[3]; + domain = a->argv[4]; + } + else + { + RTEXITCODE rcExit = readPasswordFile(a->argv[4], &passwd); + if (rcExit != RTEXITCODE_SUCCESS) + { + hrc = E_FAIL; + break; + } + domain = a->argv[5]; + } + + ComPtr<IGuest> pGuest; + CHECK_ERROR_BREAK(console, COMGETTER(Guest)(pGuest.asOutParam())); + if (!pGuest) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + CHECK_ERROR_BREAK(pGuest, SetCredentials(Bstr(a->argv[2]).raw(), + Bstr(passwd).raw(), + Bstr(domain).raw(), + fAllowLocalLogon)); + } + else if (!strcmp(a->argv[1], "guestmemoryballoon")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_GUESTMEMORYBALLOON); + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + uint32_t uVal; + int vrc; + vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); + if (vrc != VINF_SUCCESS) + { + errorSyntax(ControlVM::tr("Error parsing guest memory balloon size '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + /* guest is running; update IGuest */ + ComPtr<IGuest> pGuest; + hrc = console->COMGETTER(Guest)(pGuest.asOutParam()); + if (SUCCEEDED(hrc)) + { + if (!pGuest) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + CHECK_ERROR(pGuest, COMSETTER(MemoryBalloonSize)(uVal)); + } + } + else if (!strcmp(a->argv[1], "teleport")) + { + Bstr bstrHostname; + uint32_t uMaxDowntime = 250 /*ms*/; + uint32_t uPort = UINT32_MAX; + uint32_t cMsTimeout = 0; + Utf8Str strPassword; + static const RTGETOPTDEF s_aTeleportOptions[] = + { + { "--host", 'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */ + { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 }, + { "--port", 'P', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */ + { "--passwordfile", 'p', RTGETOPT_REQ_STRING }, + { "--password", 'W', RTGETOPT_REQ_STRING }, + { "--timeout", 't', RTGETOPT_REQ_UINT32 }, + { "--detailed-progress", 'D', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetOptState; + RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTeleportOptions, RT_ELEMENTS(s_aTeleportOptions), 2, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_TELEPORT); + int ch; + RTGETOPTUNION Value; + while ( SUCCEEDED(hrc) + && (ch = RTGetOpt(&GetOptState, &Value))) + { + switch (ch) + { + case 'h': bstrHostname = Value.psz; break; + case 'd': uMaxDowntime = Value.u32; break; + case 'D': g_fDetailedProgress = true; break; + case 'P': uPort = Value.u32; break; + case 'p': + { + RTEXITCODE rcExit = readPasswordFile(Value.psz, &strPassword); + if (rcExit != RTEXITCODE_SUCCESS) + hrc = E_FAIL; + break; + } + case 'W': strPassword = Value.psz; break; + case 't': cMsTimeout = Value.u32; break; + default: + errorGetOpt(ch, &Value); + hrc = E_FAIL; + break; + } + } + if (FAILED(hrc)) + break; + + ComPtr<IProgress> progress; + CHECK_ERROR_BREAK(console, Teleport(bstrHostname.raw(), uPort, + Bstr(strPassword).raw(), + uMaxDowntime, + progress.asOutParam())); + + if (cMsTimeout) + { + hrc = progress->COMSETTER(Timeout)(cMsTimeout); + if (FAILED(hrc) && hrc != VBOX_E_INVALID_OBJECT_STATE) + CHECK_ERROR_BREAK(progress, COMSETTER(Timeout)(cMsTimeout)); /* lazyness */ + } + + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR(progress, (ControlVM::tr("Teleportation failed"))); + } + else if (!strcmp(a->argv[1], "screenshotpng")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_SCREENSHOTPNG); + if (a->argc <= 2 || a->argc > 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + int vrc; + uint32_t iScreen = 0; + if (a->argc == 4) + { + vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &iScreen); + if (vrc != VINF_SUCCESS) + { + errorSyntax(ControlVM::tr("Error parsing display number '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + } + ComPtr<IDisplay> pDisplay; + CHECK_ERROR_BREAK(console, COMGETTER(Display)(pDisplay.asOutParam())); + if (!pDisplay) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + ULONG width, height, bpp; + LONG xOrigin, yOrigin; + GuestMonitorStatus_T monitorStatus; + CHECK_ERROR_BREAK(pDisplay, GetScreenResolution(iScreen, &width, &height, &bpp, &xOrigin, &yOrigin, &monitorStatus)); + com::SafeArray<BYTE> saScreenshot; + CHECK_ERROR_BREAK(pDisplay, TakeScreenShotToArray(iScreen, width, height, BitmapFormat_PNG, ComSafeArrayAsOutParam(saScreenshot))); + RTFILE pngFile = NIL_RTFILE; + vrc = RTFileOpen(&pngFile, a->argv[2], RTFILE_O_OPEN_CREATE | RTFILE_O_WRITE | RTFILE_O_TRUNCATE | RTFILE_O_DENY_ALL); + if (RT_FAILURE(vrc)) + { + RTMsgError(ControlVM::tr("Failed to create file '%s' (%Rrc)."), a->argv[2], vrc); + hrc = E_FAIL; + break; + } + vrc = RTFileWrite(pngFile, saScreenshot.raw(), saScreenshot.size(), NULL); + if (RT_FAILURE(vrc)) + { + RTMsgError(ControlVM::tr("Failed to write screenshot to file '%s' (%Rrc)."), a->argv[2], vrc); + hrc = E_FAIL; + } + RTFileClose(pngFile); + } +#ifdef VBOX_WITH_RECORDING + else if ( !strcmp(a->argv[1], "recording") + || !strcmp(a->argv[1], "videocap") /* legacy command */) + { + if (a->argc < 3) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + ComPtr<IRecordingSettings> recordingSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam())); + + SafeIfaceArray <IRecordingScreenSettings> saRecordingScreenScreens; + CHECK_ERROR_BREAK(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saRecordingScreenScreens))); + + ComPtr<IGraphicsAdapter> pGraphicsAdapter; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam())); + + /* Note: For now all screens have the same configuration. */ + + /* + * Note: Commands starting with "vcp" are the deprecated versions and are + * kept to ensure backwards compatibility. + */ + bool fEnabled; + if (RT_SUCCESS(parseBool(a->argv[2], &fEnabled))) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING); + CHECK_ERROR_RET(recordingSettings, COMSETTER(Enabled)(fEnabled), RTEXITCODE_FAILURE); + } + else if (!strcmp(a->argv[2], "screens")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_SCREENS); + ULONG cMonitors = 64; + CHECK_ERROR_BREAK(pGraphicsAdapter, COMGETTER(MonitorCount)(&cMonitors)); + com::SafeArray<BOOL> saScreens(cMonitors); + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + if (RT_FAILURE(parseScreens(a->argv[3], &saScreens))) + { + errorSyntax(ControlVM::tr("Error parsing list of screen IDs '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(Enabled)(saScreens[i])); + } + else if (!strcmp(a->argv[2], "filename")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_FILENAME); + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(Filename)(Bstr(a->argv[3]).raw())); + } + else if ( !strcmp(a->argv[2], "videores") + || !strcmp(a->argv[2], "videoresolution")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_VIDEORES); + if (a->argc != 5) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + uint32_t uWidth; + int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uWidth); + if (RT_FAILURE(vrc)) + { + errorSyntax(ControlVM::tr("Error parsing video width '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + + uint32_t uHeight; + vrc = RTStrToUInt32Ex(a->argv[4], NULL, 0, &uHeight); + if (RT_FAILURE(vrc)) + { + errorSyntax(ControlVM::tr("Error parsing video height '%s'."), a->argv[4]); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + { + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(VideoWidth)(uWidth)); + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(VideoHeight)(uHeight)); + } + } + else if (!strcmp(a->argv[2], "videorate")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_VIDEORATE); + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + uint32_t uRate; + int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uRate); + if (RT_FAILURE(vrc)) + { + errorSyntax(ControlVM::tr("Error parsing video rate '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(VideoRate)(uRate)); + } + else if (!strcmp(a->argv[2], "videofps")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_VIDEOFPS); + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + uint32_t uFPS; + int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uFPS); + if (RT_FAILURE(vrc)) + { + errorSyntax(ControlVM::tr("Error parsing video FPS '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(VideoFPS)(uFPS)); + } + else if (!strcmp(a->argv[2], "maxtime")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_MAXTIME); + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + uint32_t uMaxTime; + int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uMaxTime); + if (RT_FAILURE(vrc)) + { + errorSyntax(ControlVM::tr("Error parsing maximum time '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(MaxTime)(uMaxTime)); + } + else if (!strcmp(a->argv[2], "maxfilesize")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_MAXFILESIZE); + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + uint32_t uMaxFileSize; + int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uMaxFileSize); + if (RT_FAILURE(vrc)) + { + errorSyntax(ControlVM::tr("Error parsing maximum file size '%s'."), a->argv[3]); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(MaxFileSize)(uMaxFileSize)); + } + else if (!strcmp(a->argv[2], "opts")) + { +#if 0 /* Add when the corresponding documentation is enabled. */ + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_RECORDING_OPTS); +#endif + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(Options)(Bstr(a->argv[3]).raw())); + } + } +#endif /* VBOX_WITH_RECORDING */ + else if (!strcmp(a->argv[1], "webcam")) + { + if (a->argc < 3) + { + errorArgument(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + ComPtr<IEmulatedUSB> pEmulatedUSB; + CHECK_ERROR_BREAK(console, COMGETTER(EmulatedUSB)(pEmulatedUSB.asOutParam())); + if (!pEmulatedUSB) + { + RTMsgError(ControlVM::tr("Guest not running.")); + hrc = E_FAIL; + break; + } + + if (!strcmp(a->argv[2], "attach")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_WEBCAM_ATTACH); + Bstr path(""); + if (a->argc >= 4) + path = a->argv[3]; + Bstr settings(""); + if (a->argc >= 5) + settings = a->argv[4]; + CHECK_ERROR_BREAK(pEmulatedUSB, WebcamAttach(path.raw(), settings.raw())); + } + else if (!strcmp(a->argv[2], "detach")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_WEBCAM_DETACH); + Bstr path(""); + if (a->argc >= 4) + path = a->argv[3]; + CHECK_ERROR_BREAK(pEmulatedUSB, WebcamDetach(path.raw())); + } + else if (!strcmp(a->argv[2], "list")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_WEBCAM_LIST); + com::SafeArray <BSTR> webcams; + CHECK_ERROR_BREAK(pEmulatedUSB, COMGETTER(Webcams)(ComSafeArrayAsOutParam(webcams))); + for (size_t i = 0; i < webcams.size(); ++i) + { + RTPrintf("%ls\n", webcams[i][0]? webcams[i]: Bstr("default").raw()); + } + } + else + { + errorArgument(ControlVM::tr("Invalid argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + } + else if (!strcmp(a->argv[1], "addencpassword")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_ADDENCPASSWORD); + if ( a->argc != 4 + && a->argc != 6) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + break; + } + + BOOL fRemoveOnSuspend = FALSE; + if (a->argc == 6) + { + if ( strcmp(a->argv[4], "--removeonsuspend") + || ( strcmp(a->argv[5], "yes") + && strcmp(a->argv[5], "no"))) + { + errorSyntax(ControlVM::tr("Invalid parameters.")); + break; + } + if (!strcmp(a->argv[5], "yes")) + fRemoveOnSuspend = TRUE; + } + + Bstr bstrPwId(a->argv[2]); + Utf8Str strPassword; + + if (!RTStrCmp(a->argv[3], "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, ControlVM::tr("Enter password:")); + if (rcExit == RTEXITCODE_FAILURE) + break; + } + else + { + RTEXITCODE rcExit = readPasswordFile(a->argv[3], &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError(ControlVM::tr("Failed to read new password from file.")); + break; + } + } + + CHECK_ERROR_BREAK(console, AddEncryptionPassword(bstrPwId.raw(), Bstr(strPassword).raw(), fRemoveOnSuspend)); + } + else if (!strcmp(a->argv[1], "removeencpassword")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_REMOVEENCPASSWORD); + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect number of parameters.")); + break; + } + Bstr bstrPwId(a->argv[2]); + CHECK_ERROR_BREAK(console, RemoveEncryptionPassword(bstrPwId.raw())); + } + else if (!strcmp(a->argv[1], "removeallencpasswords")) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_REMOVEALLENCPASSWORDS); + CHECK_ERROR_BREAK(console, ClearAllEncryptionPasswords()); + } + else if (!strncmp(a->argv[1], "changeuartmode", 14)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_CHANGEUARTMODE); + unsigned n = parseNum(&a->argv[1][14], 4, "UART"); + if (!n) + { + hrc = E_FAIL; + break; + } + if (a->argc < 3) + { + errorSyntax(ControlVM::tr("Missing argument to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + ComPtr<ISerialPort> uart; + + CHECK_ERROR_BREAK(sessionMachine, GetSerialPort(n - 1, uart.asOutParam())); + ASSERT(uart); + + if (!RTStrICmp(a->argv[2], "disconnected")) + { + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect arguments to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_Disconnected)); + } + else if ( !RTStrICmp(a->argv[2], "server") + || !RTStrICmp(a->argv[2], "client") + || !RTStrICmp(a->argv[2], "tcpserver") + || !RTStrICmp(a->argv[2], "tcpclient") + || !RTStrICmp(a->argv[2], "file")) + { + const char *pszMode = a->argv[2]; + if (a->argc != 4) + { + errorSyntax(ControlVM::tr("Incorrect arguments to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + + CHECK_ERROR(uart, COMSETTER(Path)(Bstr(a->argv[3]).raw())); + + /* + * Change to disconnected first to get changes in just a parameter causing + * the correct changes later on. + */ + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_Disconnected)); + if (!RTStrICmp(pszMode, "server")) + { + CHECK_ERROR(uart, COMSETTER(Server)(TRUE)); + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_HostPipe)); + } + else if (!RTStrICmp(pszMode, "client")) + { + CHECK_ERROR(uart, COMSETTER(Server)(FALSE)); + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_HostPipe)); + } + else if (!RTStrICmp(pszMode, "tcpserver")) + { + CHECK_ERROR(uart, COMSETTER(Server)(TRUE)); + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_TCP)); + } + else if (!RTStrICmp(pszMode, "tcpclient")) + { + CHECK_ERROR(uart, COMSETTER(Server)(FALSE)); + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_TCP)); + } + else if (!RTStrICmp(pszMode, "file")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_RawFile)); + } + } + else + { + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect arguments to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + CHECK_ERROR(uart, COMSETTER(Path)(Bstr(a->argv[2]).raw())); + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_HostDevice)); + } + } + else if (!strncmp(a->argv[1], "vm-process-priority", 14)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_VM_PROCESS_PRIORITY); + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect arguments to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + VMProcPriority_T enmPriority = nameToVMProcPriority(a->argv[2]); + if (enmPriority == VMProcPriority_Invalid) + { + errorSyntax(ControlVM::tr("Invalid vm-process-priority '%s'."), a->argv[2]); + hrc = E_FAIL; + } + else + { + CHECK_ERROR(sessionMachine, COMSETTER(VMProcessPriority)(enmPriority)); + } + break; + } + else if (!strncmp(a->argv[1], "autostart-enabled", 17)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_AUTOSTART_ENABLED); + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect arguments to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + bool fEnabled; + if (RT_FAILURE(parseBool(a->argv[2], &fEnabled))) + { + errorSyntax(ControlVM::tr("Invalid value '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR(sessionMachine, COMSETTER(AutostartEnabled)(TRUE)); + fNeedsSaving = true; + break; + } + else if (!strncmp(a->argv[1], "autostart-delay", 15)) + { + setCurrentSubcommand(HELP_SCOPE_CONTROLVM_AUTOSTART_DELAY); + if (a->argc != 3) + { + errorSyntax(ControlVM::tr("Incorrect arguments to '%s'."), a->argv[1]); + hrc = E_FAIL; + break; + } + uint32_t u32; + char *pszNext; + int vrc = RTStrToUInt32Ex(a->argv[2], &pszNext, 10, &u32); + if (RT_FAILURE(vrc) || *pszNext != '\0') + { + errorSyntax(ControlVM::tr("Invalid autostart delay number '%s'."), a->argv[2]); + hrc = E_FAIL; + break; + } + CHECK_ERROR(sessionMachine, COMSETTER(AutostartDelay)(u32)); + if (SUCCEEDED(hrc)) + fNeedsSaving = true; + break; + } + else + { + errorSyntax(ControlVM::tr("Invalid parameter '%s'."), a->argv[1]); + hrc = E_FAIL; + } + } while (0); + + /* The client has to trigger saving the state explicitely. */ + if (fNeedsSaving) + CHECK_ERROR(sessionMachine, SaveSettings()); + + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp new file mode 100644 index 00000000..c7b420ac --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp @@ -0,0 +1,1343 @@ +/* $Id: VBoxManageDHCPServer.cpp $ */ +/** @file + * VBoxManage - Implementation of dhcpserver command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/cidr.h> +#include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/net.h> +#include <iprt/getopt.h> +#include <iprt/ctype.h> + +#include <VBox/log.h> + +#include "VBoxManage.h" + +#include <vector> +#include <map> + +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(DHCPServer); + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define DHCPD_CMD_COMMON_OPT_NETWORK 999 /**< The --network / --netname option number. */ +#define DHCPD_CMD_COMMON_OPT_INTERFACE 998 /**< The --interface / --ifname option number. */ +/** Common option definitions. */ +#define DHCPD_CMD_COMMON_OPTION_DEFS() \ + { "--network", DHCPD_CMD_COMMON_OPT_NETWORK, RTGETOPT_REQ_STRING }, \ + { "--netname", DHCPD_CMD_COMMON_OPT_NETWORK, RTGETOPT_REQ_STRING }, /* legacy */ \ + { "--interface", DHCPD_CMD_COMMON_OPT_INTERFACE, RTGETOPT_REQ_STRING }, \ + { "--ifname", DHCPD_CMD_COMMON_OPT_INTERFACE, RTGETOPT_REQ_STRING } /* legacy */ + +/** Handles common options in the typical option parsing switch. */ +#define DHCPD_CMD_COMMON_OPTION_CASES(a_pCtx, a_ch, a_pValueUnion) \ + case DHCPD_CMD_COMMON_OPT_NETWORK: \ + if ((a_pCtx)->pszInterface != NULL) \ + return errorSyntax(DHCPServer::tr("Either --network or --interface, not both")); \ + (a_pCtx)->pszNetwork = ValueUnion.psz; \ + break; \ + case DHCPD_CMD_COMMON_OPT_INTERFACE: \ + if ((a_pCtx)->pszNetwork != NULL) \ + return errorSyntax(DHCPServer::tr("Either --interface or --network, not both")); \ + (a_pCtx)->pszInterface = ValueUnion.psz; \ + break + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** Pointer to a dhcpserver command context. */ +typedef struct DHCPDCMDCTX *PDHCPDCMDCTX; + +/** + * Definition of a dhcpserver command, with handler and various flags. + */ +typedef struct DHCPDCMDDEF +{ + /** The command name. */ + const char *pszName; + + /** + * Actual command handler callback. + * + * @param pCtx Pointer to command context to use. + */ + DECLR3CALLBACKMEMBER(RTEXITCODE, pfnHandler, (PDHCPDCMDCTX pCtx, int argc, char **argv)); + + /** The sub-command scope flags. */ + uint64_t fSubcommandScope; +} DHCPDCMDDEF; +/** Pointer to a const dhcpserver command definition. */ +typedef DHCPDCMDDEF const *PCDHCPDCMDDEF; + +/** + * dhcpserver command context (mainly for carrying common options and such). + */ +typedef struct DHCPDCMDCTX +{ + /** The handler arguments from the main() function. */ + HandlerArg *pArg; + /** Pointer to the command definition. */ + PCDHCPDCMDDEF pCmdDef; + /** The network name. */ + const char *pszNetwork; + /** The (trunk) interface name. */ + const char *pszInterface; +} DHCPDCMDCTX; + +typedef std::pair<DHCPOption_T, Utf8Str> DhcpOptSpec; +typedef std::vector<DhcpOptSpec> DhcpOpts; +typedef DhcpOpts::iterator DhcpOptIterator; + +typedef std::vector<DHCPOption_T> DhcpOptIds; +typedef DhcpOptIds::iterator DhcpOptIdIterator; + +struct VmNameSlotKey +{ + const Utf8Str VmName; + uint8_t u8Slot; + + VmNameSlotKey(const Utf8Str &aVmName, uint8_t aSlot) + : VmName(aVmName) + , u8Slot(aSlot) + {} + + bool operator<(const VmNameSlotKey& that) const + { + if (VmName == that.VmName) + return u8Slot < that.u8Slot; + return VmName < that.VmName; + } +}; + +typedef std::map<VmNameSlotKey, DhcpOpts> VmSlot2OptionsM; +typedef VmSlot2OptionsM::iterator VmSlot2OptionsIterator; +typedef VmSlot2OptionsM::value_type VmSlot2OptionsPair; + +typedef std::map<VmNameSlotKey, DhcpOptIds> VmSlot2OptionIdsM; +typedef VmSlot2OptionIdsM::iterator VmSlot2OptionIdsIterator; + + + +/** + * Helper that find the DHCP server instance. + * + * @returns The DHCP server instance. NULL if failed (complaining done). + * @param pCtx The DHCP server command context. + */ +static ComPtr<IDHCPServer> dhcpdFindServer(PDHCPDCMDCTX pCtx) +{ + ComPtr<IDHCPServer> ptrRet; + if (pCtx->pszNetwork || pCtx->pszInterface) + { + Assert(pCtx->pszNetwork == NULL || pCtx->pszInterface == NULL); + + /* + * We need a network name to find the DHCP server. So, if interface is + * given we have to look it up. + */ + HRESULT hrc; + Bstr bstrNetName(pCtx->pszNetwork); + if (!pCtx->pszNetwork) + { + ComPtr<IHost> ptrIHost; + CHECK_ERROR2_RET(hrc, pCtx->pArg->virtualBox, COMGETTER(Host)(ptrIHost.asOutParam()), ptrRet); + + Bstr bstrInterface(pCtx->pszInterface); + ComPtr<IHostNetworkInterface> ptrIHostIf; + CHECK_ERROR2(hrc, ptrIHost, FindHostNetworkInterfaceByName(bstrInterface.raw(), ptrIHostIf.asOutParam())); + if (FAILED(hrc)) + { + errorArgument(DHCPServer::tr("Failed to locate host-only interface '%s'"), pCtx->pszInterface); + return ptrRet; + } + + CHECK_ERROR2_RET(hrc, ptrIHostIf, COMGETTER(NetworkName)(bstrNetName.asOutParam()), ptrRet); + } + + /* + * Now, try locate the server + */ + hrc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(bstrNetName.raw(), ptrRet.asOutParam()); + if (SUCCEEDED(hrc)) + return ptrRet; + if (pCtx->pszNetwork) + errorArgument(DHCPServer::tr("Failed to find DHCP server for network '%s'"), pCtx->pszNetwork); + else + errorArgument(DHCPServer::tr("Failed to find DHCP server for host-only interface '%s' (network '%ls')"), + pCtx->pszInterface, bstrNetName.raw()); + } + else + errorSyntax(DHCPServer::tr("You need to specify either --network or --interface to identify the DHCP server")); + return ptrRet; +} + + +/** + * Helper class for dhcpdHandleAddAndModify + */ +class DHCPCmdScope +{ + DHCPConfigScope_T m_enmScope; + const char *m_pszName; + uint8_t m_uSlot; + ComPtr<IDHCPConfig> m_ptrConfig; + ComPtr<IDHCPGlobalConfig> m_ptrGlobalConfig; + ComPtr<IDHCPGroupConfig> m_ptrGroupConfig; + ComPtr<IDHCPIndividualConfig> m_ptrIndividualConfig; + +public: + DHCPCmdScope() + : m_enmScope(DHCPConfigScope_Global) + , m_pszName(NULL) + , m_uSlot(0) + { + } + + void setGlobal() + { + m_enmScope = DHCPConfigScope_Global; + m_pszName = NULL; + m_uSlot = 0; + resetPointers(); + } + + void setGroup(const char *pszGroup) + { + m_enmScope = DHCPConfigScope_Group; + m_pszName = pszGroup; + m_uSlot = 0; + resetPointers(); + } + + void setMachineNIC(const char *pszMachine) + { + m_enmScope = DHCPConfigScope_MachineNIC; + m_pszName = pszMachine; + m_uSlot = 0; + resetPointers(); + } + + void setMachineSlot(uint8_t uSlot) + { + Assert(m_enmScope == DHCPConfigScope_MachineNIC); + m_uSlot = uSlot; + resetPointers(); + } + + void setMACAddress(const char *pszMACAddress) + { + m_enmScope = DHCPConfigScope_MAC; + m_pszName = pszMACAddress; + m_uSlot = 0; + resetPointers(); + } + + ComPtr<IDHCPConfig> &getConfig(ComPtr<IDHCPServer> const &ptrDHCPServer) + { + if (m_ptrConfig.isNull()) + { + CHECK_ERROR2I_STMT(ptrDHCPServer, GetConfig(m_enmScope, Bstr(m_pszName).raw(), m_uSlot, TRUE /*mayAdd*/, + m_ptrConfig.asOutParam()), m_ptrConfig.setNull()); + } + return m_ptrConfig; + } + + ComPtr<IDHCPIndividualConfig> &getIndividual(ComPtr<IDHCPServer> const &ptrDHCPServer) + { + getConfig(ptrDHCPServer); + if (m_ptrIndividualConfig.isNull() && m_ptrConfig.isNotNull()) + { + HRESULT hrc = m_ptrConfig.queryInterfaceTo(m_ptrIndividualConfig.asOutParam()); + if (FAILED(hrc)) + { + com::GlueHandleComError(m_ptrConfig, "queryInterface", hrc, __FILE__, __LINE__); + m_ptrIndividualConfig.setNull(); + } + } + return m_ptrIndividualConfig; + } + + ComPtr<IDHCPGroupConfig> &getGroup(ComPtr<IDHCPServer> const &ptrDHCPServer) + { + getConfig(ptrDHCPServer); + if (m_ptrGroupConfig.isNull() && m_ptrConfig.isNotNull()) + { + HRESULT hrc = m_ptrConfig.queryInterfaceTo(m_ptrGroupConfig.asOutParam()); + if (FAILED(hrc)) + { + com::GlueHandleComError(m_ptrConfig, "queryInterface", hrc, __FILE__, __LINE__); + m_ptrGroupConfig.setNull(); + } + } + return m_ptrGroupConfig; + } + + DHCPConfigScope_T getScope() const { return m_enmScope; } + +private: + void resetPointers() + { + m_ptrConfig.setNull(); + m_ptrGlobalConfig.setNull(); + m_ptrIndividualConfig.setNull(); + m_ptrGroupConfig.setNull(); + } +}; + +enum +{ + DHCP_ADDMOD = 1000, + DHCP_ADDMOD_FORCE_OPTION, + DHCP_ADDMOD_UNFORCE_OPTION, + DHCP_ADDMOD_SUPPRESS_OPTION, + DHCP_ADDMOD_UNSUPPRESS_OPTION, + DHCP_ADDMOD_ZAP_OPTIONS, + DHCP_ADDMOD_INCL_MAC, + DHCP_ADDMOD_EXCL_MAC, + DHCP_ADDMOD_DEL_MAC, + DHCP_ADDMOD_INCL_MAC_WILD, + DHCP_ADDMOD_EXCL_MAC_WILD, + DHCP_ADDMOD_DEL_MAC_WILD, + DHCP_ADDMOD_INCL_VENDOR, + DHCP_ADDMOD_EXCL_VENDOR, + DHCP_ADDMOD_DEL_VENDOR, + DHCP_ADDMOD_INCL_VENDOR_WILD, + DHCP_ADDMOD_EXCL_VENDOR_WILD, + DHCP_ADDMOD_DEL_VENDOR_WILD, + DHCP_ADDMOD_INCL_USER, + DHCP_ADDMOD_EXCL_USER, + DHCP_ADDMOD_DEL_USER, + DHCP_ADDMOD_INCL_USER_WILD, + DHCP_ADDMOD_EXCL_USER_WILD, + DHCP_ADDMOD_DEL_USER_WILD, + DHCP_ADDMOD_ZAP_CONDITIONS +}; + +/** + * Handles the 'add' and 'modify' subcommands. + */ +static DECLCALLBACK(RTEXITCODE) dhcpdHandleAddAndModify(PDHCPDCMDCTX pCtx, int argc, char **argv) +{ + static const RTGETOPTDEF s_aOptions[] = + { + DHCPD_CMD_COMMON_OPTION_DEFS(), + { "--server-ip", 'a', RTGETOPT_REQ_STRING }, + { "--ip", 'a', RTGETOPT_REQ_STRING }, // deprecated + { "-ip", 'a', RTGETOPT_REQ_STRING }, // deprecated + { "--netmask", 'm', RTGETOPT_REQ_STRING }, + { "-netmask", 'm', RTGETOPT_REQ_STRING }, // deprecated + { "--lower-ip", 'l', RTGETOPT_REQ_STRING }, + { "--lowerip", 'l', RTGETOPT_REQ_STRING }, + { "-lowerip", 'l', RTGETOPT_REQ_STRING }, // deprecated + { "--upper-ip", 'u', RTGETOPT_REQ_STRING }, + { "--upperip", 'u', RTGETOPT_REQ_STRING }, + { "-upperip", 'u', RTGETOPT_REQ_STRING }, // deprecated + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "-enable", 'e', RTGETOPT_REQ_NOTHING }, // deprecated + { "--disable", 'd', RTGETOPT_REQ_NOTHING }, + { "-disable", 'd', RTGETOPT_REQ_NOTHING }, // deprecated + { "--global", 'g', RTGETOPT_REQ_NOTHING }, + { "--group", 'G', RTGETOPT_REQ_STRING }, + { "--mac-address", 'E', RTGETOPT_REQ_MACADDR }, + { "--vm", 'M', RTGETOPT_REQ_STRING }, + { "--nic", 'n', RTGETOPT_REQ_UINT8 }, + { "--set-opt", 's', RTGETOPT_REQ_UINT8 }, + { "--set-opt-hex", 'x', RTGETOPT_REQ_UINT8 }, + { "--del-opt", 'D', RTGETOPT_REQ_UINT8 }, + { "--force-opt", DHCP_ADDMOD_FORCE_OPTION, RTGETOPT_REQ_UINT8 }, + { "--unforce-opt", DHCP_ADDMOD_UNFORCE_OPTION, RTGETOPT_REQ_UINT8 }, + { "--suppress-opt", DHCP_ADDMOD_SUPPRESS_OPTION, RTGETOPT_REQ_UINT8 }, + { "--unsuppress-opt", DHCP_ADDMOD_UNSUPPRESS_OPTION, RTGETOPT_REQ_UINT8 }, + { "--zap-options", DHCP_ADDMOD_ZAP_OPTIONS, RTGETOPT_REQ_NOTHING }, + { "--min-lease-time", 'q' , RTGETOPT_REQ_UINT32 }, + { "--default-lease-time", 'L' , RTGETOPT_REQ_UINT32 }, + { "--max-lease-time", 'Q' , RTGETOPT_REQ_UINT32 }, + { "--remove-config", 'R', RTGETOPT_REQ_NOTHING }, + { "--fixed-address", 'f', RTGETOPT_REQ_STRING }, + /* group conditions: */ + { "--incl-mac", DHCP_ADDMOD_INCL_MAC, RTGETOPT_REQ_STRING }, + { "--excl-mac", DHCP_ADDMOD_EXCL_MAC, RTGETOPT_REQ_STRING }, + { "--del-mac", DHCP_ADDMOD_DEL_MAC, RTGETOPT_REQ_STRING }, + { "--incl-mac-wild", DHCP_ADDMOD_INCL_MAC_WILD, RTGETOPT_REQ_STRING }, + { "--excl-mac-wild", DHCP_ADDMOD_EXCL_MAC_WILD, RTGETOPT_REQ_STRING }, + { "--del-mac-wild", DHCP_ADDMOD_DEL_MAC_WILD, RTGETOPT_REQ_STRING }, + { "--incl-vendor", DHCP_ADDMOD_INCL_VENDOR, RTGETOPT_REQ_STRING }, + { "--excl-vendor", DHCP_ADDMOD_EXCL_VENDOR, RTGETOPT_REQ_STRING }, + { "--del-vendor", DHCP_ADDMOD_DEL_VENDOR, RTGETOPT_REQ_STRING }, + { "--incl-vendor-wild", DHCP_ADDMOD_INCL_VENDOR_WILD, RTGETOPT_REQ_STRING }, + { "--excl-vendor-wild", DHCP_ADDMOD_EXCL_VENDOR_WILD, RTGETOPT_REQ_STRING }, + { "--del-vendor-wild", DHCP_ADDMOD_DEL_VENDOR_WILD, RTGETOPT_REQ_STRING }, + { "--incl-user", DHCP_ADDMOD_INCL_USER, RTGETOPT_REQ_STRING }, + { "--excl-user", DHCP_ADDMOD_EXCL_USER, RTGETOPT_REQ_STRING }, + { "--del-user", DHCP_ADDMOD_DEL_USER, RTGETOPT_REQ_STRING }, + { "--incl-user-wild", DHCP_ADDMOD_INCL_USER_WILD, RTGETOPT_REQ_STRING }, + { "--excl-user-wild", DHCP_ADDMOD_EXCL_USER_WILD, RTGETOPT_REQ_STRING }, + { "--del-user-wild", DHCP_ADDMOD_DEL_USER_WILD, RTGETOPT_REQ_STRING }, + { "--zap-conditions", DHCP_ADDMOD_ZAP_CONDITIONS, RTGETOPT_REQ_NOTHING }, + /* obsolete, to be removed: */ + { "--id", 'i', RTGETOPT_REQ_UINT8 }, // obsolete, backwards compatibility only. + { "--value", 'p', RTGETOPT_REQ_STRING }, // obsolete, backwards compatibility only. + { "--remove", 'r', RTGETOPT_REQ_NOTHING }, // obsolete, backwards compatibility only. + { "--options", 'o', RTGETOPT_REQ_NOTHING }, // obsolete legacy, ignored + + }; + + /* + * Parse the arguments in two passes: + * + * 1. Validate the command line and establish the IDHCPServer settings. + * 2. Execute the various IDHCPConfig settings changes. + * + * This is considered simpler than duplicating the command line instructions + * into elaborate structures and executing these. + */ + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + ComPtr<IDHCPServer> ptrDHCPServer; + for (size_t iPass = 0; iPass < 2; iPass++) + { + const char *pszServerIp = NULL; + const char *pszNetmask = NULL; + const char *pszLowerIp = NULL; + const char *pszUpperIp = NULL; + int fEnabled = -1; + + DHCPCmdScope Scope; + char szMACAddress[32]; + + bool fNeedValueOrRemove = false; /* Only used with --id; remove in 6.1+ */ + uint8_t u8OptId = 0; /* Only used too keep --id for following --value/--remove. remove in 6.1+ */ + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion))) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion); + case 'a': // --server-ip + pszServerIp = ValueUnion.psz; + break; + case 'm': // --netmask + pszNetmask = ValueUnion.psz; + break; + case 'l': // --lower-ip + pszLowerIp = ValueUnion.psz; + break; + case 'u': // --upper-ip + pszUpperIp = ValueUnion.psz; + break; + case 'e': // --enable + fEnabled = 1; + break; + case 'd': // --disable + fEnabled = 0; + break; + + /* + * Configuration selection: + */ + case 'g': // --global Sets the option scope to 'global'. + if (fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("Incomplete option sequence preseeding '--global'")); + Scope.setGlobal(); + break; + + case 'G': // --group + if (fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("Incomplete option sequence preseeding '--group'")); + if (!*ValueUnion.psz) + return errorSyntax(DHCPServer::tr("Group name cannot be empty")); + Scope.setGroup(ValueUnion.psz); + break; + + case 'E': // --mac-address + if (fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("Incomplete option sequence preseeding '--mac-address'")); + RTStrPrintf(szMACAddress, sizeof(szMACAddress), "%RTmac", &ValueUnion.MacAddr); + Scope.setMACAddress(szMACAddress); + break; + + case 'M': // --vm Sets the option scope to ValueUnion.psz + 0. + if (fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("Incomplete option sequence preseeding '--vm'")); + Scope.setMachineNIC(ValueUnion.psz); + break; + + case 'n': // --nic Sets the option scope to pszVmName + (ValueUnion.u8 - 1). + if (Scope.getScope() != DHCPConfigScope_MachineNIC) + return errorSyntax(DHCPServer::tr("--nic option requires a --vm preceeding selecting the VM it should apply to")); + if (fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("Incomplete option sequence preseeding '--nic=%u"), ValueUnion.u8); + if (ValueUnion.u8 < 1) + return errorSyntax(DHCPServer::tr("invalid NIC number: %u"), ValueUnion.u8); + Scope.setMachineSlot(ValueUnion.u8 - 1); + break; + + /* + * Modify configuration: + */ + case 's': // --set-opt num stringvalue + { + uint8_t const idAddOpt = ValueUnion.u8; + vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorFetchValue(1, "--set-opt", vrc, &ValueUnion); + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, SetOption((DHCPOption_T)idAddOpt, DHCPOptionEncoding_Normal, + Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE); + } + break; + } + + case 'x': // --set-opt-hex num hex-string + { + uint8_t const idAddOpt = ValueUnion.u8; + vrc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorFetchValue(1, "--set-opt-hex", vrc, &ValueUnion); + uint8_t abBuf[256]; + size_t cbRet; + vrc = RTStrConvertHexBytesEx(ValueUnion.psz, abBuf, sizeof(abBuf), RTSTRCONVERTHEXBYTES_F_SEP_COLON, + NULL, &cbRet); + if (RT_FAILURE(vrc)) + return errorArgument(DHCPServer::tr("Malformed hex string given to --set-opt-hex %u: %s\n"), + idAddOpt, ValueUnion.psz); + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, SetOption((DHCPOption_T)idAddOpt, DHCPOptionEncoding_Hex, + Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE); + } + break; + } + + case 'D': // --del-opt num + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + return errorSyntax(DHCPServer::tr("--del-opt does not apply to the 'add' subcommand")); + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, RemoveOption((DHCPOption_T)ValueUnion.u8), rcExit = RTEXITCODE_FAILURE); + } + break; + + case DHCP_ADDMOD_UNFORCE_OPTION: // --unforce-opt + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + return errorSyntax(DHCPServer::tr("--unforce-opt does not apply to the 'add' subcommand")); + RT_FALL_THROUGH(); + case DHCP_ADDMOD_UNSUPPRESS_OPTION: // --unsupress-opt + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + return errorSyntax(DHCPServer::tr("--unsuppress-opt does not apply to the 'add' subcommand")); + RT_FALL_THROUGH(); + case DHCP_ADDMOD_FORCE_OPTION: // --force-opt + case DHCP_ADDMOD_SUPPRESS_OPTION: // --suppress-opt + if (iPass == 1) + { + DHCPOption_T const enmOption = (DHCPOption_T)ValueUnion.u8; + bool const fForced = vrc == DHCP_ADDMOD_FORCE_OPTION || vrc == DHCP_ADDMOD_UNFORCE_OPTION; + + /* Get the current option list: */ + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + com::SafeArray<DHCPOption_T> Options; + if (fForced) + CHECK_ERROR2I_STMT(ptrConfig, COMGETTER(ForcedOptions)(ComSafeArrayAsOutParam(Options)), + rcExit = RTEXITCODE_FAILURE; break); + else + CHECK_ERROR2I_STMT(ptrConfig, COMGETTER(SuppressedOptions)(ComSafeArrayAsOutParam(Options)), + rcExit = RTEXITCODE_FAILURE; break); + if (vrc == DHCP_ADDMOD_FORCE_OPTION || vrc == DHCP_ADDMOD_SUPPRESS_OPTION) + { + /* Add if not present. */ + size_t iSrc; + for (iSrc = 0; iSrc < Options.size(); iSrc++) + if (Options[iSrc] == enmOption) + break; + if (iSrc < Options.size()) + break; /* already present */ + Options.push_back(enmOption); + } + else + { + /* Remove */ + size_t iDst = 0; + for (size_t iSrc = 0; iSrc < Options.size(); iSrc++) + { + DHCPOption_T enmCurOpt = Options[iSrc]; + if (enmCurOpt != enmOption) + Options[iDst++] = enmCurOpt; + } + if (iDst == Options.size()) + break; /* Not found. */ + Options.resize(iDst); + } + + /* Update the option list: */ + if (fForced) + CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(ForcedOptions)(ComSafeArrayAsInParam(Options)), + rcExit = RTEXITCODE_FAILURE); + else + CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(SuppressedOptions)(ComSafeArrayAsInParam(Options)), + rcExit = RTEXITCODE_FAILURE); + } + break; + + case DHCP_ADDMOD_ZAP_OPTIONS: + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + return errorSyntax(DHCPServer::tr("--zap-options does not apply to the 'add' subcommand")); + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, RemoveAllOptions(), rcExit = RTEXITCODE_FAILURE); + } + break; + + case 'q': // --min-lease-time + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(MinLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE); + } + break; + + case 'L': // --default-lease-time + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(DefaultLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE); + } + break; + + case 'Q': // --max-lease-time + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, COMSETTER(MaxLeaseTime)(ValueUnion.u32), rcExit = RTEXITCODE_FAILURE); + } + break; + + case 'R': // --remove-config + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + return errorSyntax(DHCPServer::tr("--remove-config does not apply to the 'add' subcommand")); + if (Scope.getScope() == DHCPConfigScope_Global) + return errorSyntax(DHCPServer::tr("--remove-config cannot be applied to the global config")); + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, Remove(), rcExit = RTEXITCODE_FAILURE); + } + Scope.setGlobal(); + break; + + case 'f': // --fixed-address + if (Scope.getScope() != DHCPConfigScope_MachineNIC && Scope.getScope() != DHCPConfigScope_MAC) + return errorSyntax(DHCPServer::tr("--fixed-address can only be applied to a VM NIC or an MAC address")); + if (iPass == 1) + { + ComPtr<IDHCPIndividualConfig> &ptrIndividualConfig = Scope.getIndividual(ptrDHCPServer); + if (ptrIndividualConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrIndividualConfig, COMSETTER(FixedAddress)(Bstr(ValueUnion.psz).raw()), + rcExit = RTEXITCODE_FAILURE); + } + break; + + /* + * Group conditions: + */ + case DHCP_ADDMOD_INCL_MAC: + case DHCP_ADDMOD_EXCL_MAC: + case DHCP_ADDMOD_DEL_MAC: + case DHCP_ADDMOD_INCL_MAC_WILD: + case DHCP_ADDMOD_EXCL_MAC_WILD: + case DHCP_ADDMOD_DEL_MAC_WILD: + case DHCP_ADDMOD_INCL_VENDOR: + case DHCP_ADDMOD_EXCL_VENDOR: + case DHCP_ADDMOD_DEL_VENDOR: + case DHCP_ADDMOD_INCL_VENDOR_WILD: + case DHCP_ADDMOD_EXCL_VENDOR_WILD: + case DHCP_ADDMOD_DEL_VENDOR_WILD: + case DHCP_ADDMOD_INCL_USER: + case DHCP_ADDMOD_EXCL_USER: + case DHCP_ADDMOD_DEL_USER: + case DHCP_ADDMOD_INCL_USER_WILD: + case DHCP_ADDMOD_EXCL_USER_WILD: + case DHCP_ADDMOD_DEL_USER_WILD: + { + if (Scope.getScope() != DHCPConfigScope_Group) + return errorSyntax(DHCPServer::tr("A group must be selected to perform condition alterations.")); + if (!*ValueUnion.psz) + return errorSyntax(DHCPServer::tr("Condition value cannot be empty")); /* or can it? */ + if (iPass != 1) + break; + + DHCPGroupConditionType_T enmType; + switch (vrc) + { + case DHCP_ADDMOD_INCL_MAC: case DHCP_ADDMOD_EXCL_MAC: case DHCP_ADDMOD_DEL_MAC: + enmType = DHCPGroupConditionType_MAC; + break; + case DHCP_ADDMOD_INCL_MAC_WILD: case DHCP_ADDMOD_EXCL_MAC_WILD: case DHCP_ADDMOD_DEL_MAC_WILD: + enmType = DHCPGroupConditionType_MACWildcard; + break; + case DHCP_ADDMOD_INCL_VENDOR: case DHCP_ADDMOD_EXCL_VENDOR: case DHCP_ADDMOD_DEL_VENDOR: + enmType = DHCPGroupConditionType_vendorClassID; + break; + case DHCP_ADDMOD_INCL_VENDOR_WILD: case DHCP_ADDMOD_EXCL_VENDOR_WILD: case DHCP_ADDMOD_DEL_VENDOR_WILD: + enmType = DHCPGroupConditionType_vendorClassIDWildcard; + break; + case DHCP_ADDMOD_INCL_USER: case DHCP_ADDMOD_EXCL_USER: case DHCP_ADDMOD_DEL_USER: + enmType = DHCPGroupConditionType_userClassID; + break; + case DHCP_ADDMOD_INCL_USER_WILD: case DHCP_ADDMOD_EXCL_USER_WILD: case DHCP_ADDMOD_DEL_USER_WILD: + enmType = DHCPGroupConditionType_userClassIDWildcard; + break; + default: + AssertFailedReturn(RTEXITCODE_FAILURE); + } + + int fInclusive; + switch (vrc) + { + case DHCP_ADDMOD_DEL_MAC: + case DHCP_ADDMOD_DEL_MAC_WILD: + case DHCP_ADDMOD_DEL_USER: + case DHCP_ADDMOD_DEL_USER_WILD: + case DHCP_ADDMOD_DEL_VENDOR: + case DHCP_ADDMOD_DEL_VENDOR_WILD: + fInclusive = -1; + break; + case DHCP_ADDMOD_EXCL_MAC: + case DHCP_ADDMOD_EXCL_MAC_WILD: + case DHCP_ADDMOD_EXCL_USER: + case DHCP_ADDMOD_EXCL_USER_WILD: + case DHCP_ADDMOD_EXCL_VENDOR: + case DHCP_ADDMOD_EXCL_VENDOR_WILD: + fInclusive = 0; + break; + case DHCP_ADDMOD_INCL_MAC: + case DHCP_ADDMOD_INCL_MAC_WILD: + case DHCP_ADDMOD_INCL_USER: + case DHCP_ADDMOD_INCL_USER_WILD: + case DHCP_ADDMOD_INCL_VENDOR: + case DHCP_ADDMOD_INCL_VENDOR_WILD: + fInclusive = 1; + break; + default: + AssertFailedReturn(RTEXITCODE_FAILURE); + } + + ComPtr<IDHCPGroupConfig> &ptrGroupConfig = Scope.getGroup(ptrDHCPServer); + if (ptrGroupConfig.isNull()) + return RTEXITCODE_FAILURE; + if (fInclusive >= 0) + { + ComPtr<IDHCPGroupCondition> ptrCondition; + CHECK_ERROR2I_STMT(ptrGroupConfig, AddCondition((BOOL)fInclusive, enmType, Bstr(ValueUnion.psz).raw(), + ptrCondition.asOutParam()), rcExit = RTEXITCODE_FAILURE); + } + else + { + com::SafeIfaceArray<IDHCPGroupCondition> Conditions; + CHECK_ERROR2I_STMT(ptrGroupConfig, COMGETTER(Conditions)(ComSafeArrayAsOutParam(Conditions)), + rcExit = RTEXITCODE_FAILURE; break); + bool fFound = false; + for (size_t iCond = 0; iCond < Conditions.size(); iCond++) + { + DHCPGroupConditionType_T enmCurType = DHCPGroupConditionType_MAC; + CHECK_ERROR2I_STMT(Conditions[iCond], COMGETTER(Type)(&enmCurType), + rcExit = RTEXITCODE_FAILURE; continue); + if (enmCurType == enmType) + { + Bstr bstrValue; + CHECK_ERROR2I_STMT(Conditions[iCond], COMGETTER(Value)(bstrValue.asOutParam()), + rcExit = RTEXITCODE_FAILURE; continue); + if (RTUtf16CmpUtf8(bstrValue.raw(), ValueUnion.psz) == 0) + { + CHECK_ERROR2I_STMT(Conditions[iCond], Remove(), rcExit = RTEXITCODE_FAILURE); + fFound = true; + } + } + } + if (!fFound) + rcExit = RTMsgErrorExitFailure(DHCPServer::tr("Could not find any condition of type %d with value '%s' to delete"), + enmType, ValueUnion.psz); + } + break; + } + + case DHCP_ADDMOD_ZAP_CONDITIONS: + if (Scope.getScope() != DHCPConfigScope_Group) + return errorSyntax(DHCPServer::tr("--zap-conditions can only be with a group selected")); + if (iPass == 1) + { + ComPtr<IDHCPGroupConfig> &ptrGroupConfig = Scope.getGroup(ptrDHCPServer); + if (ptrGroupConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrGroupConfig, RemoveAllConditions(), rcExit = RTEXITCODE_FAILURE); + } + break; + + /* + * For backwards compatibility. Remove in 6.1 or later. + */ + + case 'o': // --options - obsolete, ignored. + break; + + case 'i': // --id + if (fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("Incomplete option sequence preseeding '--id=%u"), ValueUnion.u8); + u8OptId = ValueUnion.u8; + fNeedValueOrRemove = true; + break; + + case 'p': // --value + if (!fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("--value without --id=dhcp-opt-no")); + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, SetOption((DHCPOption_T)u8OptId, DHCPOptionEncoding_Normal, + Bstr(ValueUnion.psz).raw()), rcExit = RTEXITCODE_FAILURE); + } + fNeedValueOrRemove = false; + break; + + case 'r': // --remove + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + return errorSyntax(DHCPServer::tr("--remove does not apply to the 'add' subcommand")); + if (!fNeedValueOrRemove) + return errorSyntax(DHCPServer::tr("--remove without --id=dhcp-opt-no")); + + if (iPass == 1) + { + ComPtr<IDHCPConfig> &ptrConfig = Scope.getConfig(ptrDHCPServer); + if (ptrConfig.isNull()) + return RTEXITCODE_FAILURE; + CHECK_ERROR2I_STMT(ptrConfig, RemoveOption((DHCPOption_T)u8OptId), rcExit = RTEXITCODE_FAILURE); + } + fNeedValueOrRemove = false; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (iPass != 0) + break; + + /* + * Ensure we've got mandatory options and supply defaults + * where needed (modify case) + */ + if (!pCtx->pszNetwork && !pCtx->pszInterface) + return errorSyntax(DHCPServer::tr("You need to specify either --network or --interface to identify the DHCP server")); + + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + { + if (!pszServerIp) + rcExit = errorSyntax(DHCPServer::tr("Missing required option: --ip")); + if (!pszNetmask) + rcExit = errorSyntax(DHCPServer::tr("Missing required option: --netmask")); + if (!pszLowerIp) + rcExit = errorSyntax(DHCPServer::tr("Missing required option: --lowerip")); + if (!pszUpperIp) + rcExit = errorSyntax(DHCPServer::tr("Missing required option: --upperip")); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + } + + /* + * Find or create the server. + */ + HRESULT hrc; + Bstr NetName; + if (!pCtx->pszNetwork) + { + ComPtr<IHost> host; + CHECK_ERROR(pCtx->pArg->virtualBox, COMGETTER(Host)(host.asOutParam())); + + ComPtr<IHostNetworkInterface> hif; + CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam())); + if (FAILED(hrc)) + return errorArgument(DHCPServer::tr("Could not find interface '%s'"), pCtx->pszInterface); + + CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam())); + if (FAILED(hrc)) + return errorArgument(DHCPServer::tr("Could not get network name for the interface '%s'"), pCtx->pszInterface); + } + else + { + NetName = Bstr(pCtx->pszNetwork); + } + + hrc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(NetName.mutableRaw(), ptrDHCPServer.asOutParam()); + if (pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD) + { + if (SUCCEEDED(hrc)) + return errorArgument(DHCPServer::tr("DHCP server already exists")); + + CHECK_ERROR(pCtx->pArg->virtualBox, CreateDHCPServer(NetName.mutableRaw(), ptrDHCPServer.asOutParam())); + if (FAILED(hrc)) + return errorArgument(DHCPServer::tr("Failed to create the DHCP server")); + } + else if (FAILED(hrc)) + return errorArgument(DHCPServer::tr("DHCP server does not exist")); + + /* + * Apply IDHCPServer settings: + */ + if (pszServerIp || pszNetmask || pszLowerIp || pszUpperIp) + { + Bstr bstrServerIp(pszServerIp); + Bstr bstrNetmask(pszNetmask); + Bstr bstrLowerIp(pszLowerIp); + Bstr bstrUpperIp(pszUpperIp); + + if (!pszServerIp) + { + CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(IPAddress)(bstrServerIp.asOutParam()), RTEXITCODE_FAILURE); + } + if (!pszNetmask) + { + CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(NetworkMask)(bstrNetmask.asOutParam()), RTEXITCODE_FAILURE); + } + if (!pszLowerIp) + { + CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(LowerIP)(bstrLowerIp.asOutParam()), RTEXITCODE_FAILURE); + } + if (!pszUpperIp) + { + CHECK_ERROR2_RET(hrc, ptrDHCPServer, COMGETTER(UpperIP)(bstrUpperIp.asOutParam()), RTEXITCODE_FAILURE); + } + + CHECK_ERROR2_STMT(hrc, ptrDHCPServer, SetConfiguration(bstrServerIp.raw(), bstrNetmask.raw(), + bstrLowerIp.raw(), bstrUpperIp.raw()), + rcExit = errorArgument(DHCPServer::tr("Failed to set configuration (%ls, %ls, %ls, %ls)"), bstrServerIp.raw(), + bstrNetmask.raw(), bstrLowerIp.raw(), bstrUpperIp.raw())); + } + + if (fEnabled >= 0) + { + CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMSETTER(Enabled)((BOOL)fEnabled), rcExit = RTEXITCODE_FAILURE); + } + } + + return rcExit; +} + + +/** + * Handles the 'remove' subcommand. + */ +static DECLCALLBACK(RTEXITCODE) dhcpdHandleRemove(PDHCPDCMDCTX pCtx, int argc, char **argv) +{ + /* + * Parse the command line. + */ + static const RTGETOPTDEF s_aOptions[] = + { + DHCPD_CMD_COMMON_OPTION_DEFS(), + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion))) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion); + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Locate the server and perform the requested operation. + */ + ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx); + if (ptrDHCPServer.isNotNull()) + { + HRESULT hrc; + CHECK_ERROR2(hrc, pCtx->pArg->virtualBox, RemoveDHCPServer(ptrDHCPServer)); + if (SUCCEEDED(hrc)) + return RTEXITCODE_SUCCESS; + errorArgument(DHCPServer::tr("Failed to remove server")); + } + return RTEXITCODE_FAILURE; +} + + +/** + * Handles the 'start' subcommand. + */ +static DECLCALLBACK(RTEXITCODE) dhcpdHandleStart(PDHCPDCMDCTX pCtx, int argc, char **argv) +{ + /* + * Parse the command line. + */ + static const RTGETOPTDEF s_aOptions[] = + { + DHCPD_CMD_COMMON_OPTION_DEFS(), + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion))) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion); + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Locate the server. + */ + ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx); + if (ptrDHCPServer.isNotNull()) + { + /* + * We have to figure out the trunk name and type here, which is silly to + * leave to the API client as it's a pain to get right. But here we go... + */ + static char const s_szHostOnlyPrefix[] = "HostInterfaceNetworking-"; + bool fHostOnly = true; + Bstr strTrunkName; + if (pCtx->pszInterface) + strTrunkName = pCtx->pszInterface; + else if (RTStrStartsWith(pCtx->pszNetwork, s_szHostOnlyPrefix)) + strTrunkName = &pCtx->pszNetwork[sizeof(s_szHostOnlyPrefix) - 1]; + else + fHostOnly = false; + + Bstr strTrunkType; + if (fHostOnly) +#if defined(RT_OS_WINDOWS) || defined(RT_OS_DARWIN) + strTrunkType = "netadp"; +#else /* lazy implementations: */ + strTrunkType = "netflt"; +#endif + else + strTrunkType = "whatever"; + + HRESULT hrc = ptrDHCPServer->Start(strTrunkName.raw(), strTrunkType.raw()); + if (SUCCEEDED(hrc)) + return RTEXITCODE_SUCCESS; + errorArgument(DHCPServer::tr("Failed to start the server")); + GlueHandleComErrorNoCtx(ptrDHCPServer, hrc); + } + return RTEXITCODE_FAILURE; +} + + +/** + * Handles the 'restart' subcommand. + */ +static DECLCALLBACK(RTEXITCODE) dhcpdHandleRestart(PDHCPDCMDCTX pCtx, int argc, char **argv) +{ + /* + * Parse the command line. + */ + static const RTGETOPTDEF s_aOptions[] = + { + DHCPD_CMD_COMMON_OPTION_DEFS(), + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion))) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion); + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Locate the server and perform the requested operation. + */ + ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx); + if (ptrDHCPServer.isNotNull()) + { + HRESULT hrc = ptrDHCPServer->Restart(); + if (SUCCEEDED(hrc)) + return RTEXITCODE_SUCCESS; + errorArgument(DHCPServer::tr("Failed to restart the server")); + GlueHandleComErrorNoCtx(ptrDHCPServer, hrc); + } + return RTEXITCODE_FAILURE; +} + + +/** + * Handles the 'stop' subcommand. + */ +static DECLCALLBACK(RTEXITCODE) dhcpdHandleStop(PDHCPDCMDCTX pCtx, int argc, char **argv) +{ + /* + * Parse the command line. + */ + static const RTGETOPTDEF s_aOptions[] = + { + DHCPD_CMD_COMMON_OPTION_DEFS(), + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion))) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion); + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Locate the server and perform the requested operation. + */ + ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx); + if (ptrDHCPServer.isNotNull()) + { + HRESULT hrc = ptrDHCPServer->Stop(); + if (SUCCEEDED(hrc)) + return RTEXITCODE_SUCCESS; + errorArgument(DHCPServer::tr("Failed to stop the server")); + GlueHandleComErrorNoCtx(ptrDHCPServer, hrc); + } + return RTEXITCODE_FAILURE; +} + + +/** + * Handles the 'findlease' subcommand. + */ +static DECLCALLBACK(RTEXITCODE) dhcpdHandleFindLease(PDHCPDCMDCTX pCtx, int argc, char **argv) +{ + /* + * Parse the command line. + */ + static const RTGETOPTDEF s_aOptions[] = + { + DHCPD_CMD_COMMON_OPTION_DEFS(), + { "--mac-address", 'm', RTGETOPT_REQ_MACADDR }, + + }; + + bool fHaveMacAddress = false; + RTMAC MacAddress = { { 0, 0, 0, 0, 0, 0 } }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion))) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion); + + case 'm': // --mac-address + fHaveMacAddress = true; + MacAddress = ValueUnion.MacAddr; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (!fHaveMacAddress) + return errorSyntax(DHCPServer::tr("You need to specify a MAC address too look for")); + + /* + * Locate the server and perform the requested operation. + */ + ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx); + if (ptrDHCPServer.isNull()) + return RTEXITCODE_FAILURE; + + char szMac[32]; + RTStrPrintf(szMac, sizeof(szMac), "%RTmac", &MacAddress); + Bstr bstrAddress; + Bstr bstrState; + LONG64 secIssued = 0; + LONG64 secExpire = 0; + HRESULT hrc; + CHECK_ERROR2(hrc, ptrDHCPServer, FindLeaseByMAC(Bstr(szMac).raw(), 0 /*type*/, + bstrAddress.asOutParam(), bstrState.asOutParam(), &secIssued, &secExpire)); + if (SUCCEEDED(hrc)) + { + RTTIMESPEC TimeSpec; + int64_t cSecLeftToLive = secExpire - RTTimeSpecGetSeconds(RTTimeNow(&TimeSpec)); + RTTIME Time; + char szIssued[RTTIME_STR_LEN]; + RTTimeToStringEx(RTTimeExplode(&Time, RTTimeSpecSetSeconds(&TimeSpec, secIssued)), szIssued, sizeof(szIssued), 0); + char szExpire[RTTIME_STR_LEN]; + RTTimeToStringEx(RTTimeExplode(&Time, RTTimeSpecSetSeconds(&TimeSpec, secExpire)), szExpire, sizeof(szExpire), 0); + + RTPrintf(DHCPServer::tr("IP Address: %ls\n" + "MAC Address: %RTmac\n" + "State: %ls\n" + "Issued: %s (%RU64)\n" + "Expire: %s (%RU64)\n" + "TTL: %RU64 sec, currently %RU64 sec left\n"), + bstrAddress.raw(), + &MacAddress, + bstrState.raw(), + szIssued, secIssued, + szExpire, secExpire, + secExpire >= secIssued ? secExpire - secIssued : 0, cSecLeftToLive > 0 ? cSecLeftToLive : 0); + return RTEXITCODE_SUCCESS; + } + return RTEXITCODE_FAILURE; +} + + +/** + * Handles the 'dhcpserver' command. + */ +RTEXITCODE handleDHCPServer(HandlerArg *pArg) +{ + /* + * Command definitions. + */ + static const DHCPDCMDDEF s_aCmdDefs[] = + { + { "add", dhcpdHandleAddAndModify, HELP_SCOPE_DHCPSERVER_ADD }, + { "modify", dhcpdHandleAddAndModify, HELP_SCOPE_DHCPSERVER_MODIFY }, + { "remove", dhcpdHandleRemove, HELP_SCOPE_DHCPSERVER_REMOVE }, + { "start", dhcpdHandleStart, HELP_SCOPE_DHCPSERVER_START }, + { "restart", dhcpdHandleRestart, HELP_SCOPE_DHCPSERVER_RESTART }, + { "stop", dhcpdHandleStop, HELP_SCOPE_DHCPSERVER_STOP }, + { "findlease", dhcpdHandleFindLease, HELP_SCOPE_DHCPSERVER_FINDLEASE }, + }; + + /* + * VBoxManage dhcpserver [common-options] subcommand ... + */ + DHCPDCMDCTX CmdCtx; + CmdCtx.pArg = pArg; + CmdCtx.pCmdDef = NULL; + CmdCtx.pszInterface = NULL; + CmdCtx.pszNetwork = NULL; + + static const RTGETOPTDEF s_CommonOptions[] = { DHCPD_CMD_COMMON_OPTION_DEFS() }; + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, pArg->argc, pArg->argv, s_CommonOptions, RT_ELEMENTS(s_CommonOptions), 0, + 0 /* No sorting! */); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + DHCPD_CMD_COMMON_OPTION_CASES(&CmdCtx, vrc, &ValueUnion); + + case VINF_GETOPT_NOT_OPTION: + { + const char *pszCmd = ValueUnion.psz; + uint32_t iCmd; + for (iCmd = 0; iCmd < RT_ELEMENTS(s_aCmdDefs); iCmd++) + if (strcmp(s_aCmdDefs[iCmd].pszName, pszCmd) == 0) + { + CmdCtx.pCmdDef = &s_aCmdDefs[iCmd]; + setCurrentSubcommand(s_aCmdDefs[iCmd].fSubcommandScope); + return s_aCmdDefs[iCmd].pfnHandler(&CmdCtx, pArg->argc - GetState.iNext + 1, + &pArg->argv[GetState.iNext - 1]); + } + return errorUnknownSubcommand(pszCmd); + } + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + return errorNoSubcommand(); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp new file mode 100644 index 00000000..39c0866e --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp @@ -0,0 +1,976 @@ +/* $Id: VBoxManageDebugVM.cpp $ */ +/** @file + * VBoxManage - Implementation of the debugvm command. + */ + +/* + * Copyright (C) 2012-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <VBox/types.h> +#include <iprt/ctype.h> +#include <iprt/getopt.h> +#include <iprt/path.h> +#include <iprt/param.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/uuid.h> +#include <VBox/log.h> + +#include "VBoxManage.h" + +DECLARE_TRANSLATION_CONTEXT(DebugVM); + + +/** + * Handles the getregisters sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * We take a list of register names (case insensitive). If 'all' is + * encountered we'll dump all registers. + */ + ULONG idCpu = 0; + unsigned cRegisters = 0; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'c': + idCpu = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!RTStrICmp(ValueUnion.psz, "all")) + { + com::SafeArray<BSTR> aBstrNames; + com::SafeArray<BSTR> aBstrValues; + CHECK_ERROR2I_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames), + ComSafeArrayAsOutParam(aBstrValues)), + RTEXITCODE_FAILURE); + Assert(aBstrNames.size() == aBstrValues.size()); + + size_t cchMaxName = 8; + for (size_t i = 0; i < aBstrNames.size(); i++) + { + size_t cchName = RTUtf16Len(aBstrNames[i]); + if (cchName > cchMaxName) + cchMaxName = cchName; + } + + for (size_t i = 0; i < aBstrNames.size(); i++) + RTPrintf("%-*ls = %ls\n", cchMaxName, aBstrNames[i], aBstrValues[i]); + } + else + { + com::Bstr bstrName = ValueUnion.psz; + com::Bstr bstrValue; + CHECK_ERROR2I_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw()); + } + cRegisters++; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (!cRegisters) + return errorSyntax(DebugVM::tr("The getregisters sub-command takes at least one register name")); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the info sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_Info(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse arguments. + */ + const char *pszInfo = NULL; + const char *pszArgs = NULL; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, NULL, 0, 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case VINF_GETOPT_NOT_OPTION: + if (!pszInfo) + pszInfo = ValueUnion.psz; + else if (!pszArgs) + pszArgs = ValueUnion.psz; + else + return errorTooManyParameters(&pArgs->argv[GetState.iNext - 1]); + break; + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (!pszInfo) + return errorSyntax(DebugVM::tr("Must specify info item to display")); + + /* + * Do the work. + */ + com::Bstr bstrName(pszInfo); + com::Bstr bstrArgs(pszArgs); + com::Bstr bstrInfo; + CHECK_ERROR2I_RET(pDebugger, Info(bstrName.raw(), bstrArgs.raw(), bstrInfo.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf("%ls", bstrInfo.raw()); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the inject sub-command. + * + * @returns Suitable exit code. + * @param a The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_InjectNMI(HandlerArg *a, IMachineDebugger *pDebugger) +{ + if (a->argc != 2) + return errorTooManyParameters(&a->argv[1]); + CHECK_ERROR2I_RET(pDebugger, InjectNMI(), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the log sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + * @param pszSubCmd The sub command. + */ +static RTEXITCODE handleDebugVM_LogXXXX(HandlerArg *pArgs, IMachineDebugger *pDebugger, const char *pszSubCmd) +{ + /* + * Parse arguments. + */ + bool fRelease = false; + com::Utf8Str strSettings; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + + /* + * NB: don't use short options to prevent log specifications like + * "-drv_foo" from being interpreted as options. + */ +# define DEBUGVM_LOG_DEBUG (VINF_GETOPT_NOT_OPTION + 'd') +# define DEBUGVM_LOG_RELEASE (VINF_GETOPT_NOT_OPTION + 'r') + + static const RTGETOPTDEF s_aOptions[] = + { + { "--debug", DEBUGVM_LOG_DEBUG, RTGETOPT_REQ_NOTHING }, + { "--release", DEBUGVM_LOG_RELEASE, RTGETOPT_REQ_NOTHING } + }; + /* + * Note: RTGETOPTINIT_FLAGS_NO_STD_OPTS is needed to not get into an infinite hang in the following + * while-loop when processing log groups starting with "h", + * e.g. "VBoxManage debugvm <VM Name> log --debug -hex". + */ + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, + RTGETOPTINIT_FLAGS_OPTS_FIRST | RTGETOPTINIT_FLAGS_NO_STD_OPTS); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case DEBUGVM_LOG_RELEASE: + fRelease = true; + break; + + case DEBUGVM_LOG_DEBUG: + fRelease = false; + break; + + /* Because log strings can start with "-" (like "-all+dev_foo") + * we have to take everything we got as a setting and apply it. + * IPRT will take care of the validation afterwards. */ + default: + if (strSettings.length() == 0) + strSettings = ValueUnion.psz; + else + { + strSettings.append(' '); + strSettings.append(ValueUnion.psz); + } + break; + } + } + + if (fRelease) + { + com::Utf8Str strTmp(strSettings); + strSettings = "release:"; + strSettings.append(strTmp); + } + + com::Bstr bstrSettings(strSettings); + if (!strcmp(pszSubCmd, "log")) + CHECK_ERROR2I_RET(pDebugger, ModifyLogGroups(bstrSettings.raw()), RTEXITCODE_FAILURE); + else if (!strcmp(pszSubCmd, "logdest")) + CHECK_ERROR2I_RET(pDebugger, ModifyLogDestinations(bstrSettings.raw()), RTEXITCODE_FAILURE); + else if (!strcmp(pszSubCmd, "logflags")) + CHECK_ERROR2I_RET(pDebugger, ModifyLogFlags(bstrSettings.raw()), RTEXITCODE_FAILURE); + else + AssertFailedReturn(RTEXITCODE_FAILURE); + + return RTEXITCODE_SUCCESS; +} + + +/** + * Handles the inject sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_DumpVMCore(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse arguments. + */ + const char *pszFilename = NULL; + const char *pszCompression = NULL; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--filename", 'f', RTGETOPT_REQ_STRING }, + { "--compression", 'c', RTGETOPT_REQ_STRING } + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'c': + if (pszCompression) + return errorSyntax(DebugVM::tr("The --compression option has already been given")); + pszCompression = ValueUnion.psz; + break; + case 'f': + if (pszFilename) + return errorSyntax(DebugVM::tr("The --filename option has already been given")); + pszFilename = ValueUnion.psz; + break; + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (!pszFilename) + return errorSyntax(DebugVM::tr("The --filename option is required")); + + /* + * Make the filename absolute before handing it on to the API. + */ + char szAbsFilename[RTPATH_MAX]; + vrc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, DebugVM::tr("RTPathAbs failed on '%s': %Rrc"), pszFilename, vrc); + + com::Bstr bstrFilename(szAbsFilename); + com::Bstr bstrCompression(pszCompression); + CHECK_ERROR2I_RET(pDebugger, DumpGuestCore(bstrFilename.raw(), bstrCompression.raw()), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the osdetect sub-command. + * + * @returns Suitable exit code. + * @param a The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_OSDetect(HandlerArg *a, IMachineDebugger *pDebugger) +{ + if (a->argc != 2) + return errorTooManyParameters(&a->argv[1]); + + com::Bstr bstrIgnore; + com::Bstr bstrAll("all"); + CHECK_ERROR2I_RET(pDebugger, LoadPlugIn(bstrAll.raw(), bstrIgnore.asOutParam()), RTEXITCODE_FAILURE); + + com::Bstr bstrName; + CHECK_ERROR2I_RET(pDebugger, DetectOS(bstrName.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf(DebugVM::tr("Detected: %ls\n"), bstrName.raw()); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the osinfo sub-command. + * + * @returns Suitable exit code. + * @param a The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_OSInfo(HandlerArg *a, IMachineDebugger *pDebugger) +{ + if (a->argc != 2) + return errorTooManyParameters(&a->argv[1]); + + com::Bstr bstrName; + CHECK_ERROR2I_RET(pDebugger, COMGETTER(OSName)(bstrName.asOutParam()), RTEXITCODE_FAILURE); + com::Bstr bstrVersion; + CHECK_ERROR2I_RET(pDebugger, COMGETTER(OSVersion)(bstrVersion.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf(DebugVM::tr("Name: %ls\n"), bstrName.raw()); + RTPrintf(DebugVM::tr("Version: %ls\n"), bstrVersion.raw()); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the osdmsg sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_OSDmesg(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse argument. + */ + uint32_t uMaxMessages = 0; + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--lines", 'n', RTGETOPT_REQ_UINT32 }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + switch (vrc) + { + case 'n': uMaxMessages = ValueUnion.u32; break; + default: return errorGetOpt(vrc, &ValueUnion); + } + + /* + * Do it. + */ + com::Bstr bstrDmesg; + CHECK_ERROR2I_RET(pDebugger, QueryOSKernelLog(uMaxMessages, bstrDmesg.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf("%ls\n", bstrDmesg.raw()); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the setregisters sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_SetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * We take a list of register assignments, that is register=value. + */ + ULONG idCpu = 0; + com::SafeArray<IN_BSTR> aBstrNames; + com::SafeArray<IN_BSTR> aBstrValues; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'c': + idCpu = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + { + const char *pszEqual = strchr(ValueUnion.psz, '='); + if (!pszEqual) + return errorSyntax(DebugVM::tr("setregisters expects input on the form 'register=value' got '%s'"), + ValueUnion.psz); + try + { + com::Bstr bstrName(ValueUnion.psz, pszEqual - ValueUnion.psz); + com::Bstr bstrValue(pszEqual + 1); + if ( !aBstrNames.push_back(bstrName.raw()) + || !aBstrValues.push_back(bstrValue.raw())) + throw std::bad_alloc(); + } + catch (std::bad_alloc &) + { + RTMsgError(DebugVM::tr("Out of memory\n")); + return RTEXITCODE_FAILURE; + } + break; + } + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (!aBstrNames.size()) + return errorSyntax(DebugVM::tr("The setregisters sub-command takes at least one register name")); + + /* + * If it is only one register, use the single register method just so + * we expose it and can test it from the command line. + */ + if (aBstrNames.size() == 1) + { + CHECK_ERROR2I_RET(pDebugger, SetRegister(idCpu, aBstrNames[0], aBstrValues[0]), RTEXITCODE_FAILURE); + RTPrintf(DebugVM::tr("Successfully set %ls\n"), aBstrNames[0]); + } + else + { + CHECK_ERROR2I_RET(pDebugger, SetRegisters(idCpu, ComSafeArrayAsInParam(aBstrNames), ComSafeArrayAsInParam(aBstrValues)), + RTEXITCODE_FAILURE); + RTPrintf(DebugVM::tr("Successfully set %u registers\n", "", aBstrNames.size()), aBstrNames.size()); + } + + return RTEXITCODE_SUCCESS; +} + +/** @name debugvm show flags + * @{ */ +#define DEBUGVM_SHOW_FLAGS_HUMAN_READABLE UINT32_C(0x00000000) +#define DEBUGVM_SHOW_FLAGS_SH_EXPORT UINT32_C(0x00000001) +#define DEBUGVM_SHOW_FLAGS_SH_EVAL UINT32_C(0x00000002) +#define DEBUGVM_SHOW_FLAGS_CMD_SET UINT32_C(0x00000003) +#define DEBUGVM_SHOW_FLAGS_FMT_MASK UINT32_C(0x00000003) +/** @} */ + +/** + * Prints a variable according to the @a fFlags. + * + * @param pszVar The variable name. + * @param pbstrValue The variable value. + * @param fFlags The debugvm show flags. + */ +static void handleDebugVM_Show_PrintVar(const char *pszVar, com::Bstr const *pbstrValue, uint32_t fFlags) +{ + switch (fFlags & DEBUGVM_SHOW_FLAGS_FMT_MASK) + { + case DEBUGVM_SHOW_FLAGS_HUMAN_READABLE: RTPrintf(" %27s=%ls\n", pszVar, pbstrValue->raw()); break; + case DEBUGVM_SHOW_FLAGS_SH_EXPORT: RTPrintf(DebugVM::tr("export %s='%ls'\n"), pszVar, pbstrValue->raw()); break; + case DEBUGVM_SHOW_FLAGS_SH_EVAL: RTPrintf("%s='%ls'\n", pszVar, pbstrValue->raw()); break; + case DEBUGVM_SHOW_FLAGS_CMD_SET: RTPrintf(DebugVM::tr("set %s=%ls\n"), pszVar, pbstrValue->raw()); break; + default: AssertFailed(); + } +} + +/** + * Handles logdbg-settings. + * + * @returns Exit code. + * @param pDebugger The debugger interface. + * @param fFlags The debugvm show flags. + */ +static RTEXITCODE handleDebugVM_Show_LogDbgSettings(IMachineDebugger *pDebugger, uint32_t fFlags) +{ + if ((fFlags & DEBUGVM_SHOW_FLAGS_FMT_MASK) == DEBUGVM_SHOW_FLAGS_HUMAN_READABLE) + RTPrintf(DebugVM::tr("Debug logger settings:\n")); + + com::Bstr bstr; + CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogDbgGroups)(bstr.asOutParam()), RTEXITCODE_FAILURE); + handleDebugVM_Show_PrintVar("VBOX_LOG", &bstr, fFlags); + + CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogDbgFlags)(bstr.asOutParam()), RTEXITCODE_FAILURE); + handleDebugVM_Show_PrintVar("VBOX_LOG_FLAGS", &bstr, fFlags); + + CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogDbgDestinations)(bstr.asOutParam()), RTEXITCODE_FAILURE); + handleDebugVM_Show_PrintVar("VBOX_LOG_DEST", &bstr, fFlags); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles logrel-settings. + * + * @returns Exit code. + * @param pDebugger The debugger interface. + * @param fFlags The debugvm show flags. + */ +static RTEXITCODE handleDebugVM_Show_LogRelSettings(IMachineDebugger *pDebugger, uint32_t fFlags) +{ + if ((fFlags & DEBUGVM_SHOW_FLAGS_FMT_MASK) == DEBUGVM_SHOW_FLAGS_HUMAN_READABLE) + RTPrintf(DebugVM::tr("Release logger settings:\n")); + + com::Bstr bstr; + CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogRelGroups)(bstr.asOutParam()), RTEXITCODE_FAILURE); + handleDebugVM_Show_PrintVar("VBOX_RELEASE_LOG", &bstr, fFlags); + + CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogRelFlags)(bstr.asOutParam()), RTEXITCODE_FAILURE); + handleDebugVM_Show_PrintVar("VBOX_RELEASE_LOG_FLAGS", &bstr, fFlags); + + CHECK_ERROR2I_RET(pDebugger, COMGETTER(LogRelDestinations)(bstr.asOutParam()), RTEXITCODE_FAILURE); + handleDebugVM_Show_PrintVar("VBOX_RELEASE_LOG_DEST", &bstr, fFlags); + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the show sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_Show(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse arguments and what to show. Order dependent. + */ + uint32_t fFlags = DEBUGVM_SHOW_FLAGS_HUMAN_READABLE; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--human-readable", 'H', RTGETOPT_REQ_NOTHING }, + { "--sh-export", 'e', RTGETOPT_REQ_NOTHING }, + { "--sh-eval", 'E', RTGETOPT_REQ_NOTHING }, + { "--cmd-set", 's', RTGETOPT_REQ_NOTHING }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'H': + fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_HUMAN_READABLE; + break; + + case 'e': + fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_SH_EXPORT; + break; + + case 'E': + fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_SH_EVAL; + break; + + case 's': + fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_CMD_SET; + break; + + case VINF_GETOPT_NOT_OPTION: + { + RTEXITCODE rcExit; + if (!strcmp(ValueUnion.psz, "log-settings")) + { + rcExit = handleDebugVM_Show_LogDbgSettings(pDebugger, fFlags); + if (rcExit == RTEXITCODE_SUCCESS) + rcExit = handleDebugVM_Show_LogRelSettings(pDebugger, fFlags); + } + else if (!strcmp(ValueUnion.psz, "logdbg-settings")) + rcExit = handleDebugVM_Show_LogDbgSettings(pDebugger, fFlags); + else if (!strcmp(ValueUnion.psz, "logrel-settings")) + rcExit = handleDebugVM_Show_LogRelSettings(pDebugger, fFlags); + else + rcExit = errorSyntax(DebugVM::tr("The show sub-command has no idea what '%s' might be"), ValueUnion.psz); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + break; + } + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the stack sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_Stack(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse arguments. + */ + VMCPUID idCpu = VMCPUID_ALL; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'c': + idCpu = ValueUnion.u32; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Dump stack. + */ + com::Bstr bstrGuestStack; + if (idCpu != VMCPUID_ALL) + { + /* Single CPU */ + CHECK_ERROR2I_RET(pDebugger, DumpGuestStack(idCpu, bstrGuestStack.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf("%ls\n", bstrGuestStack.raw()); + } + else + { + /* All CPUs. */ + ComPtr<IMachine> ptrMachine; + CHECK_ERROR2I_RET(pArgs->session, COMGETTER(Machine)(ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + ULONG cCpus; + CHECK_ERROR2I_RET(ptrMachine, COMGETTER(CPUCount)(&cCpus), RTEXITCODE_FAILURE); + + for (idCpu = 0; idCpu < (VMCPUID)cCpus; idCpu++) + { + CHECK_ERROR2I_RET(pDebugger, DumpGuestStack(idCpu, bstrGuestStack.asOutParam()), RTEXITCODE_FAILURE); + if (cCpus > 1) + { + if (idCpu > 0) + RTPrintf("\n"); + RTPrintf(DebugVM::tr("====================== CPU #%u ======================\n"), idCpu); + } + RTPrintf("%ls\n", bstrGuestStack.raw()); + } + } + + + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the statistics sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_Statistics(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse arguments. + */ + bool fWithDescriptions = false; + const char *pszPattern = NULL; /* all */ + bool fReset = false; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--descriptions", 'd', RTGETOPT_REQ_NOTHING }, + { "--pattern", 'p', RTGETOPT_REQ_STRING }, + { "--reset", 'r', RTGETOPT_REQ_NOTHING }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'd': + fWithDescriptions = true; + break; + + case 'p': + if (pszPattern) + return errorSyntax(DebugVM::tr("Multiple --pattern options are not permitted")); + pszPattern = ValueUnion.psz; + break; + + case 'r': + fReset = true; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (fReset && fWithDescriptions) + return errorSyntax(DebugVM::tr("The --reset and --descriptions options does not mix")); + + /* + * Execute the order. + */ + com::Bstr bstrPattern(pszPattern); + if (fReset) + CHECK_ERROR2I_RET(pDebugger, ResetStats(bstrPattern.raw()), RTEXITCODE_FAILURE); + else + { + com::Bstr bstrStats; + CHECK_ERROR2I_RET(pDebugger, GetStats(bstrPattern.raw(), fWithDescriptions, bstrStats.asOutParam()), + RTEXITCODE_FAILURE); + /* if (fFormatted) + { big mess } + else + */ + RTPrintf("%ls\n", bstrStats.raw()); + } + + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the guestsample sub-command. + * + * @returns Suitable exit code. + * @param pArgs The handler arguments. + * @param pDebugger Pointer to the debugger interface. + */ +static RTEXITCODE handleDebugVM_GuestSample(HandlerArg *pArgs, IMachineDebugger *pDebugger) +{ + /* + * Parse arguments. + */ + const char *pszFilename = NULL; + uint32_t cSampleIntervalUs = 1000; + uint64_t cSampleTimeUs = 1000*1000; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--filename", 'f', RTGETOPT_REQ_STRING }, + { "--sample-interval-us", 'i', RTGETOPT_REQ_UINT32 }, + { "--sample-time-us", 't', RTGETOPT_REQ_UINT64 }, + }; + int vrc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 'f': + pszFilename = ValueUnion.psz; + break; + case 'i': + cSampleIntervalUs = ValueUnion.u32; + break; + case 't': + cSampleTimeUs = ValueUnion.u64; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + if (!pszFilename) + return errorSyntax(DebugVM::tr("The --filename is missing")); + + /* + * Execute the order. + */ + ComPtr<IProgress> ptrProgress; + com::Bstr bstrFilename(pszFilename); + CHECK_ERROR2I_RET(pDebugger, TakeGuestSample(bstrFilename.raw(), cSampleIntervalUs, cSampleTimeUs, ptrProgress.asOutParam()), RTEXITCODE_FAILURE); + showProgress(ptrProgress); + + return RTEXITCODE_SUCCESS; +} + +RTEXITCODE handleDebugVM(HandlerArg *pArgs) +{ + RTEXITCODE rcExit = RTEXITCODE_FAILURE; + + /* + * The first argument is the VM name or UUID. Open a session to it. + */ + if (pArgs->argc < 2) + return errorNoSubcommand(); + ComPtr<IMachine> ptrMachine; + CHECK_ERROR2I_RET(pArgs->virtualBox, FindMachine(com::Bstr(pArgs->argv[0]).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR2I_RET(ptrMachine, LockMachine(pArgs->session, LockType_Shared), RTEXITCODE_FAILURE); + + /* + * Get the associated console and machine debugger. + */ + HRESULT hrc; + ComPtr<IConsole> ptrConsole; + CHECK_ERROR2(hrc, pArgs->session, COMGETTER(Console)(ptrConsole.asOutParam())); + if (SUCCEEDED(hrc)) + { + if (ptrConsole.isNotNull()) + { + ComPtr<IMachineDebugger> ptrDebugger; + CHECK_ERROR2(hrc, ptrConsole, COMGETTER(Debugger)(ptrDebugger.asOutParam())); + if (SUCCEEDED(hrc)) + { + /* + * String switch on the sub-command. + */ + const char *pszSubCmd = pArgs->argv[1]; + if (!strcmp(pszSubCmd, "dumpvmcore")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_DUMPVMCORE); + rcExit = handleDebugVM_DumpVMCore(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "getregisters")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_GETREGISTERS); + rcExit = handleDebugVM_GetRegisters(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "info")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_INFO); + rcExit = handleDebugVM_Info(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "injectnmi")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_INJECTNMI); + rcExit = handleDebugVM_InjectNMI(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "log")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_LOG); + rcExit = handleDebugVM_LogXXXX(pArgs, ptrDebugger, pszSubCmd); + } + else if (!strcmp(pszSubCmd, "logdest")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_LOGDEST); + rcExit = handleDebugVM_LogXXXX(pArgs, ptrDebugger, pszSubCmd); + } + else if (!strcmp(pszSubCmd, "logflags")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_LOGFLAGS); + rcExit = handleDebugVM_LogXXXX(pArgs, ptrDebugger, pszSubCmd); + } + else if (!strcmp(pszSubCmd, "osdetect")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_OSDETECT); + rcExit = handleDebugVM_OSDetect(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "osinfo")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_OSINFO); + rcExit = handleDebugVM_OSInfo(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "osdmesg")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_OSDMESG); + rcExit = handleDebugVM_OSDmesg(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "setregisters")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_SETREGISTERS); + rcExit = handleDebugVM_SetRegisters(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "show")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_SHOW); + rcExit = handleDebugVM_Show(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "stack")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_STACK); + rcExit = handleDebugVM_Stack(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "statistics")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_STATISTICS); + rcExit = handleDebugVM_Statistics(pArgs, ptrDebugger); + } + else if (!strcmp(pszSubCmd, "guestsample")) + { + setCurrentSubcommand(HELP_SCOPE_DEBUGVM_GUESTSAMPLE); + rcExit = handleDebugVM_GuestSample(pArgs, ptrDebugger); + } + else + errorUnknownSubcommand(pszSubCmd); + } + } + else + RTMsgError(DebugVM::tr("Machine '%s' is not currently running.\n"), pArgs->argv[0]); + } + + pArgs->session->UnlockMachine(); + + return rcExit; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp new file mode 100644 index 00000000..1e2d8845 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp @@ -0,0 +1,2753 @@ +/* $Id: VBoxManageDisk.cpp $ */ +/** @file + * VBoxManage - The disk/medium related commands. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/asm.h> +#include <iprt/base64.h> +#include <iprt/file.h> +#include <iprt/path.h> +#include <iprt/param.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/ctype.h> +#include <iprt/getopt.h> +#include <VBox/log.h> +#include <VBox/vd.h> + +#include <list> + +#include "VBoxManage.h" +using namespace com; + +/** Medium category. */ +typedef enum MEDIUMCATEGORY +{ + MEDIUMCATEGORY_NONE = 0, + MEDIUMCATEGORY_DISK, + MEDIUMCATEGORY_DVD, + MEDIUMCATEGORY_FLOPPY +} MEDIUMCATEGORY; + +DECLARE_TRANSLATION_CONTEXT(Disk); + +// funcs +/////////////////////////////////////////////////////////////////////////////// + + +static DECLCALLBACK(void) handleVDError(void *pvUser, int vrc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) +{ + RT_NOREF(pvUser); + RTMsgErrorV(pszFormat, va); + RTMsgError(Disk::tr("Error code %Rrc at %s(%u) in function %s"), vrc, RT_SRC_POS_ARGS); +} + +static int parseMediumVariant(const char *psz, MediumVariant_T *pMediumVariant) +{ + int vrc = VINF_SUCCESS; + unsigned uMediumVariant = (unsigned)(*pMediumVariant); + while (psz && *psz && RT_SUCCESS(vrc)) + { + size_t len; + const char *pszComma = strchr(psz, ','); + if (pszComma) + len = pszComma - psz; + else + len = strlen(psz); + if (len > 0) + { + // Parsing is intentionally inconsistent: "standard" resets the + // variant, whereas the other flags are cumulative. + if (!RTStrNICmp(psz, "standard", len)) + uMediumVariant = MediumVariant_Standard; + else if ( !RTStrNICmp(psz, "fixed", len) + || !RTStrNICmp(psz, "static", len)) + uMediumVariant |= MediumVariant_Fixed; + else if (!RTStrNICmp(psz, "Diff", len)) + uMediumVariant |= MediumVariant_Diff; + else if (!RTStrNICmp(psz, "split2g", len)) + uMediumVariant |= MediumVariant_VmdkSplit2G; + else if ( !RTStrNICmp(psz, "stream", len) + || !RTStrNICmp(psz, "streamoptimized", len)) + uMediumVariant |= MediumVariant_VmdkStreamOptimized; + else if (!RTStrNICmp(psz, "esx", len)) + uMediumVariant |= MediumVariant_VmdkESX; + else if (!RTStrNICmp(psz, "formatted", len)) + uMediumVariant |= MediumVariant_Formatted; + else if ( !RTStrNICmp(psz, "raw", len) + || !RTStrNICmp(psz, "rawdisk", len)) + uMediumVariant |= MediumVariant_VmdkRawDisk; + else + vrc = VERR_PARSE_ERROR; + } + if (pszComma) + psz += len + 1; + else + psz += len; + } + + if (RT_SUCCESS(vrc)) + *pMediumVariant = (MediumVariant_T)uMediumVariant; + return vrc; +} + +int parseMediumType(const char *psz, MediumType_T *penmMediumType) +{ + int vrc = VINF_SUCCESS; + MediumType_T enmMediumType = MediumType_Normal; + if (!RTStrICmp(psz, "normal")) + enmMediumType = MediumType_Normal; + else if (!RTStrICmp(psz, "immutable")) + enmMediumType = MediumType_Immutable; + else if (!RTStrICmp(psz, "writethrough")) + enmMediumType = MediumType_Writethrough; + else if (!RTStrICmp(psz, "shareable")) + enmMediumType = MediumType_Shareable; + else if (!RTStrICmp(psz, "readonly")) + enmMediumType = MediumType_Readonly; + else if (!RTStrICmp(psz, "multiattach")) + enmMediumType = MediumType_MultiAttach; + else + vrc = VERR_PARSE_ERROR; + + if (RT_SUCCESS(vrc)) + *penmMediumType = enmMediumType; + return vrc; +} + +/** @todo move this into getopt, as getting bool values is generic */ +int parseBool(const char *psz, bool *pb) +{ + int vrc = VINF_SUCCESS; + if ( !RTStrICmp(psz, "on") + || !RTStrICmp(psz, "yes") + || !RTStrICmp(psz, "true") + || !RTStrCmp(psz, "1") + || !RTStrICmp(psz, "enable") + || !RTStrICmp(psz, "enabled")) + *pb = true; + else if ( !RTStrICmp(psz, "off") + || !RTStrICmp(psz, "no") + || !RTStrICmp(psz, "false") + || !RTStrCmp(psz, "0") + || !RTStrICmp(psz, "disable") + || !RTStrICmp(psz, "disabled")) + *pb = false; + else + vrc = VERR_PARSE_ERROR; + + return vrc; +} + +HRESULT openMedium(HandlerArg *a, const char *pszFilenameOrUuid, + DeviceType_T enmDevType, AccessMode_T enmAccessMode, + ComPtr<IMedium> &pMedium, bool fForceNewUuidOnOpen, + bool fSilent) +{ + HRESULT hrc; + Guid id(pszFilenameOrUuid); + char szFilenameAbs[RTPATH_MAX] = ""; + + /* If it is no UUID, convert the filename to an absolute one. */ + if (!id.isValid()) + { + int irc = RTPathAbs(pszFilenameOrUuid, szFilenameAbs, sizeof(szFilenameAbs)); + if (RT_FAILURE(irc)) + { + if (!fSilent) + RTMsgError(Disk::tr("Cannot convert filename \"%s\" to absolute path"), pszFilenameOrUuid); + return E_FAIL; + } + pszFilenameOrUuid = szFilenameAbs; + } + + if (!fSilent) + CHECK_ERROR(a->virtualBox, OpenMedium(Bstr(pszFilenameOrUuid).raw(), + enmDevType, + enmAccessMode, + fForceNewUuidOnOpen, + pMedium.asOutParam())); + else + hrc = a->virtualBox->OpenMedium(Bstr(pszFilenameOrUuid).raw(), + enmDevType, + enmAccessMode, + fForceNewUuidOnOpen, + pMedium.asOutParam()); + + return hrc; +} + +static HRESULT createMedium(HandlerArg *a, const char *pszFormat, + const char *pszFilename, DeviceType_T enmDevType, + AccessMode_T enmAccessMode, ComPtr<IMedium> &pMedium) +{ + HRESULT hrc; + char szFilenameAbs[RTPATH_MAX] = ""; + + /** @todo laziness shortcut. should really check the MediumFormatCapabilities */ + if (RTStrICmp(pszFormat, "iSCSI")) + { + int irc = RTPathAbs(pszFilename, szFilenameAbs, sizeof(szFilenameAbs)); + if (RT_FAILURE(irc)) + { + RTMsgError(Disk::tr("Cannot convert filename \"%s\" to absolute path"), pszFilename); + return E_FAIL; + } + pszFilename = szFilenameAbs; + } + + CHECK_ERROR(a->virtualBox, CreateMedium(Bstr(pszFormat).raw(), + Bstr(pszFilename).raw(), + enmAccessMode, + enmDevType, + pMedium.asOutParam())); + return hrc; +} + +static const RTGETOPTDEF g_aCreateMediumOptions[] = +{ + { "disk", 'H', RTGETOPT_REQ_NOTHING }, + { "dvd", 'D', RTGETOPT_REQ_NOTHING }, + { "floppy", 'L', RTGETOPT_REQ_NOTHING }, + { "--filename", 'f', RTGETOPT_REQ_STRING }, + { "-filename", 'f', RTGETOPT_REQ_STRING }, // deprecated + { "--diffparent", 'd', RTGETOPT_REQ_STRING }, + { "--size", 's', RTGETOPT_REQ_UINT64 }, + { "-size", 's', RTGETOPT_REQ_UINT64 }, // deprecated + { "--sizebyte", 'S', RTGETOPT_REQ_UINT64 }, + { "--format", 'o', RTGETOPT_REQ_STRING }, + { "-format", 'o', RTGETOPT_REQ_STRING }, // deprecated + { "--static", 'F', RTGETOPT_REQ_NOTHING }, + { "-static", 'F', RTGETOPT_REQ_NOTHING }, // deprecated + { "--variant", 'm', RTGETOPT_REQ_STRING }, + { "-variant", 'm', RTGETOPT_REQ_STRING }, // deprecated + { "--property", 'p', RTGETOPT_REQ_STRING }, + { "--property-file",'P', RTGETOPT_REQ_STRING }, +}; + +class MediumProperty +{ +public: + const char *m_pszKey; + const char *m_pszValue; /**< Can be binary too. */ + size_t m_cbValue; + char *m_pszFreeValue; + MediumProperty() : m_pszKey(NULL), m_pszValue(NULL), m_cbValue(0), m_pszFreeValue(NULL) { } + MediumProperty(MediumProperty const &a_rThat) + : m_pszKey(a_rThat.m_pszKey) + , m_pszValue(a_rThat.m_pszValue) + , m_cbValue(a_rThat.m_cbValue) + , m_pszFreeValue(NULL) + { + Assert(a_rThat.m_pszFreeValue == NULL); /* not expected here! */ + } + ~MediumProperty() + { + RTMemFree(m_pszFreeValue); + m_pszFreeValue = NULL; + } + +private: + MediumProperty &operator=(MediumProperty const &a_rThat) + { + m_pszKey = a_rThat.m_pszKey; + m_pszValue = a_rThat.m_pszValue; + m_cbValue = a_rThat.m_cbValue; + m_pszFreeValue = a_rThat.m_pszFreeValue; + if (a_rThat.m_pszFreeValue != NULL) + { + m_pszFreeValue = (char *)RTMemDup(m_pszValue, m_cbValue + 1); + if (!m_pszFreeValue) + { + RTMsgError(Disk::tr("Out of memory copying '%s'"), m_pszValue); + throw std::bad_alloc(); + } + } + return *this; + } +}; + +RTEXITCODE handleCreateMedium(HandlerArg *a) +{ + std::list<MediumProperty> lstProperties; + + HRESULT hrc; + int vrc; + const char *filename = NULL; + const char *diffparent = NULL; + uint64_t size = 0; + enum + { + CMD_NONE, + CMD_DISK, + CMD_DVD, + CMD_FLOPPY + } cmd = CMD_NONE; + const char *format = NULL; + bool fBase = true; + MediumVariant_T enmMediumVariant = MediumVariant_Standard; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aCreateMediumOptions, RT_ELEMENTS(g_aCreateMediumOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'H': // disk + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DISK; + break; + + case 'D': // DVD + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DVD; + break; + + case 'L': // floppy + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_FLOPPY; + break; + + case 'f': // --filename + filename = ValueUnion.psz; + break; + + case 'd': // --diffparent + diffparent = ValueUnion.psz; + fBase = false; + break; + + case 's': // --size + size = ValueUnion.u64 * _1M; + break; + + case 'S': // --sizebyte + size = ValueUnion.u64; + break; + + case 'o': // --format + format = ValueUnion.psz; + break; + + case 'p': // --property + case 'P': // --property-file + { + /* allocate property kvp, parse, and append to end of singly linked list */ + char *pszValue = (char *)strchr(ValueUnion.psz, '='); + if (!pszValue) + return RTMsgErrorExitFailure(Disk::tr("Invalid key value pair: No '='.")); + + lstProperties.push_back(MediumProperty()); + MediumProperty &rNewProp = lstProperties.back(); + *pszValue++ = '\0'; /* Warning! Modifies argument string. */ + rNewProp.m_pszKey = ValueUnion.psz; + if (c == 'p') + { + rNewProp.m_pszValue = pszValue; + rNewProp.m_cbValue = strlen(pszValue); + } + else // 'P' + { + RTFILE hValueFile = NIL_RTFILE; + vrc = RTFileOpen(&hValueFile, pszValue, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Disk::tr("Cannot open replacement value file '%s': %Rrc"), pszValue, vrc); + + uint64_t cbValue = 0; + vrc = RTFileQuerySize(hValueFile, &cbValue); + if (RT_SUCCESS(vrc)) + { + if (cbValue <= _16M) + { + rNewProp.m_cbValue = (size_t)cbValue; + rNewProp.m_pszValue = rNewProp.m_pszFreeValue = (char *)RTMemAlloc(rNewProp.m_cbValue + 1); + if (rNewProp.m_pszFreeValue) + { + vrc = RTFileReadAt(hValueFile, 0, rNewProp.m_pszFreeValue, cbValue, NULL); + if (RT_SUCCESS(vrc)) + rNewProp.m_pszFreeValue[rNewProp.m_cbValue] = '\0'; + else + RTMsgError(Disk::tr("Error reading replacement MBR file '%s': %Rrc"), pszValue, vrc); + } + else + vrc = RTMsgErrorRc(VERR_NO_MEMORY, Disk::tr("Out of memory reading '%s': %Rrc"), pszValue, vrc); + } + else + vrc = RTMsgErrorRc(VERR_OUT_OF_RANGE, + Disk::tr("Replacement value file '%s' is to big: %Rhcb, max 16MiB"), + pszValue, cbValue); + } + else + RTMsgError(Disk::tr("Cannot get the size of the value file '%s': %Rrc"), pszValue, vrc); + RTFileClose(hValueFile); + if (RT_FAILURE(vrc)) + return RTEXITCODE_FAILURE; + } + break; + } + + case 'F': // --static ("fixed"/"flat") + { + unsigned uMediumVariant = (unsigned)enmMediumVariant; + uMediumVariant |= MediumVariant_Fixed; + enmMediumVariant = (MediumVariant_T)uMediumVariant; + break; + } + + case 'm': // --variant + vrc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant); + if (RT_FAILURE(vrc)) + return errorArgument(Disk::tr("Invalid medium variant '%s'"), ValueUnion.psz); + break; + + case VINF_GETOPT_NOT_OPTION: + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Disk::tr("Invalid option -%c"), c); + else + return errorSyntax(Disk::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Disk::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Disk::tr("error: %Rrs"), c); + } + } + + /* check the outcome */ + if (cmd == CMD_NONE) + cmd = CMD_DISK; + ComPtr<IMedium> pParentMedium; + if (fBase) + { + if (!filename || !*filename) + return errorSyntax(Disk::tr("Parameter --filename is required")); + if ((enmMediumVariant & MediumVariant_VmdkRawDisk) == 0 && size == 0) + return errorSyntax(Disk::tr("Parameter --size is required")); + if (!format || !*format) + { + if (cmd == CMD_DISK) + format = "VDI"; + else if (cmd == CMD_DVD || cmd == CMD_FLOPPY) + { + format = "RAW"; + unsigned uMediumVariant = (unsigned)enmMediumVariant; + uMediumVariant |= MediumVariant_Fixed; + enmMediumVariant = (MediumVariant_T)uMediumVariant; + } + } + if ((enmMediumVariant & MediumVariant_VmdkRawDisk) && strcmp(format, "VMDK")) + return errorSyntax(Disk::tr("Variant 'Rawdisk' requires '--format=VMDK'")); + } + else + { + if ( !filename + || !*filename) + return errorSyntax(Disk::tr("Parameter --filename is required")); + size = 0; + if (cmd != CMD_DISK) + return errorSyntax(Disk::tr("Creating a differencing medium is only supported for hard disks")); + enmMediumVariant = MediumVariant_Diff; + if (!format || !*format) + { + const char *pszExt = RTPathSuffix(filename); + /* Skip over . if there is an extension. */ + if (pszExt) + pszExt++; + if (!pszExt || !*pszExt) + format = "VDI"; + else + format = pszExt; + } + hrc = openMedium(a, diffparent, DeviceType_HardDisk, + AccessMode_ReadWrite, pParentMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + if (pParentMedium.isNull()) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Disk::tr("Invalid parent hard disk reference, avoiding crash")); + MediumState_T state; + CHECK_ERROR(pParentMedium, COMGETTER(State)(&state)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + if (state == MediumState_Inaccessible) + { + CHECK_ERROR(pParentMedium, RefreshState(&state)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + } + } + /* check for filename extension */ + /** @todo use IMediumFormat to cover all extensions generically */ + Utf8Str strName(filename); + if (!RTPathHasSuffix(strName.c_str())) + { + Utf8Str strFormat(format); + if (cmd == CMD_DISK) + { + if (strFormat.compare("vmdk", RTCString::CaseInsensitive) == 0) + strName.append(".vmdk"); + else if (strFormat.compare("vhd", RTCString::CaseInsensitive) == 0) + strName.append(".vhd"); + else + strName.append(".vdi"); + } + else if (cmd == CMD_DVD) + strName.append(".iso"); + else if (cmd == CMD_FLOPPY) + strName.append(".img"); + filename = strName.c_str(); + } + + ComPtr<IMedium> pMedium; + if (cmd == CMD_DISK) + hrc = createMedium(a, format, filename, DeviceType_HardDisk, + AccessMode_ReadWrite, pMedium); + else if (cmd == CMD_DVD) + hrc = createMedium(a, format, filename, DeviceType_DVD, + AccessMode_ReadOnly, pMedium); + else if (cmd == CMD_FLOPPY) + hrc = createMedium(a, format, filename, DeviceType_Floppy, + AccessMode_ReadWrite, pMedium); + else + hrc = E_INVALIDARG; /* cannot happen but make gcc happy */ + + + if (SUCCEEDED(hrc) && pMedium) + { + if (lstProperties.size() > 0) + { + ComPtr<IMediumFormat> pMediumFormat; + CHECK_ERROR2I_RET(pMedium, COMGETTER(MediumFormat)(pMediumFormat.asOutParam()), RTEXITCODE_FAILURE); + com::SafeArray<BSTR> propertyNames; + com::SafeArray<BSTR> propertyDescriptions; + com::SafeArray<DataType_T> propertyTypes; + com::SafeArray<ULONG> propertyFlags; + com::SafeArray<BSTR> propertyDefaults; + CHECK_ERROR2I_RET(pMediumFormat, + DescribeProperties(ComSafeArrayAsOutParam(propertyNames), + ComSafeArrayAsOutParam(propertyDescriptions), + ComSafeArrayAsOutParam(propertyTypes), + ComSafeArrayAsOutParam(propertyFlags), + ComSafeArrayAsOutParam(propertyDefaults)), + RTEXITCODE_FAILURE); + + for (std::list<MediumProperty>::iterator it = lstProperties.begin(); + it != lstProperties.end(); + ++it) + { + const char * const pszKey = it->m_pszKey; + bool fBinary = true; + bool fPropertyFound = false; + for (size_t i = 0; i < propertyNames.size(); ++i) + if (RTUtf16CmpUtf8(propertyNames[i], pszKey) == 0) + { + fBinary = propertyTypes[i] == DataType_Int8; + fPropertyFound = true; + break; + } + if (!fPropertyFound) + return RTMsgErrorExit(RTEXITCODE_FAILURE, + Disk::tr("Property '%s' was not found in the list of medium properties for the requested medium format (%s)."), + pszKey, format); + if (!fBinary) + CHECK_ERROR2I_RET(pMedium, SetProperty(Bstr(pszKey).raw(), Bstr(it->m_pszValue).raw()), + RTEXITCODE_FAILURE); + else + { + com::Bstr bstrBase64Value; + hrc = bstrBase64Value.base64Encode(it->m_pszValue, it->m_cbValue); + if (FAILED(hrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Disk::tr("Base64 encoding of the property %s failed. (%Rhrc)"), + pszKey, hrc); + CHECK_ERROR2I_RET(pMedium, SetProperty(Bstr(pszKey).raw(), bstrBase64Value.raw()), RTEXITCODE_FAILURE); + } + } + } + + ComPtr<IProgress> pProgress; + com::SafeArray<MediumVariant_T> l_variants(sizeof(MediumVariant_T)*8); + + for (ULONG i = 0; i < l_variants.size(); ++i) + { + ULONG temp = enmMediumVariant; + temp &= 1<<i; + l_variants [i] = (MediumVariant_T)temp; + } + + if (fBase) + CHECK_ERROR(pMedium, CreateBaseStorage(size, ComSafeArrayAsInParam(l_variants), pProgress.asOutParam())); + else + CHECK_ERROR(pParentMedium, CreateDiffStorage(pMedium, ComSafeArrayAsInParam(l_variants), pProgress.asOutParam())); + if (SUCCEEDED(hrc) && pProgress) + { + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR(pProgress, (Disk::tr("Failed to create medium"))); + } + } + + if (SUCCEEDED(hrc) && pMedium) + { + Bstr uuid; + CHECK_ERROR(pMedium, COMGETTER(Id)(uuid.asOutParam())); + RTPrintf(Disk::tr("Medium created. UUID: %s\n"), Utf8Str(uuid).c_str()); + + //CHECK_ERROR(pMedium, Close()); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aModifyMediumOptions[] = +{ + { "disk", 'H', RTGETOPT_REQ_NOTHING }, + { "dvd", 'D', RTGETOPT_REQ_NOTHING }, + { "floppy", 'L', RTGETOPT_REQ_NOTHING }, + { "--type", 't', RTGETOPT_REQ_STRING }, + { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated + { "settype", 't', RTGETOPT_REQ_STRING }, // deprecated + { "--autoreset", 'z', RTGETOPT_REQ_STRING }, + { "-autoreset", 'z', RTGETOPT_REQ_STRING }, // deprecated + { "autoreset", 'z', RTGETOPT_REQ_STRING }, // deprecated + { "--property", 'p', RTGETOPT_REQ_STRING }, + { "--compact", 'c', RTGETOPT_REQ_NOTHING }, + { "-compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated + { "compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated + { "--resize", 'r', RTGETOPT_REQ_UINT64 }, + { "--resizebyte", 'R', RTGETOPT_REQ_UINT64 }, + { "--move", 'm', RTGETOPT_REQ_STRING }, + { "--setlocation", 'l', RTGETOPT_REQ_STRING }, + { "--description", 'd', RTGETOPT_REQ_STRING } +}; + +RTEXITCODE handleModifyMedium(HandlerArg *a) +{ + HRESULT hrc; + int vrc; + enum { + CMD_NONE, + CMD_DISK, + CMD_DVD, + CMD_FLOPPY + } cmd = CMD_NONE; + ComPtr<IMedium> pMedium; + MediumType_T enmMediumType = MediumType_Normal; /* Shut up MSC */ + bool AutoReset = false; + SafeArray<BSTR> mediumPropNames; + SafeArray<BSTR> mediumPropValues; + bool fModifyMediumType = false; + bool fModifyAutoReset = false; + bool fModifyProperties = false; + bool fModifyCompact = false; + bool fModifyResize = false; + bool fModifyResizeMB = false; + bool fMoveMedium = false; + bool fModifyDescription = false; + bool fSetNewLocation = false; + uint64_t cbResize = 0; + const char *pszFilenameOrUuid = NULL; + char *pszNewLocation = NULL; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aModifyMediumOptions, RT_ELEMENTS(g_aModifyMediumOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'H': // disk + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DISK; + break; + + case 'D': // DVD + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DVD; + break; + + case 'L': // floppy + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_FLOPPY; + break; + + case 't': // --type + vrc = parseMediumType(ValueUnion.psz, &enmMediumType); + if (RT_FAILURE(vrc)) + return errorArgument(Disk::tr("Invalid medium type '%s'"), ValueUnion.psz); + fModifyMediumType = true; + break; + + case 'z': // --autoreset + vrc = parseBool(ValueUnion.psz, &AutoReset); + if (RT_FAILURE(vrc)) + return errorArgument(Disk::tr("Invalid autoreset parameter '%s'"), ValueUnion.psz); + fModifyAutoReset = true; + break; + + case 'p': // --property + { + /* Parse 'name=value' */ + char *pszProperty = RTStrDup(ValueUnion.psz); + if (pszProperty) + { + char *pDelimiter = strchr(pszProperty, '='); + if (pDelimiter) + { + *pDelimiter = '\0'; + + Bstr bstrName(pszProperty); + Bstr bstrValue(&pDelimiter[1]); + bstrName.detachTo(mediumPropNames.appendedRaw()); + bstrValue.detachTo(mediumPropValues.appendedRaw()); + fModifyProperties = true; + } + else + { + errorArgument(Disk::tr("Invalid --property argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + RTStrFree(pszProperty); + } + else + { + RTStrmPrintf(g_pStdErr, Disk::tr("Error: Failed to allocate memory for medium property '%s'\n"), + ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case 'c': // --compact + fModifyCompact = true; + break; + + case 'r': // --resize + cbResize = ValueUnion.u64 * _1M; + fModifyResize = true; + fModifyResizeMB = true; // do sanity check! + break; + + case 'R': // --resizebyte + cbResize = ValueUnion.u64; + fModifyResize = true; + break; + + case 'm': // --move + /* Get a new location */ + pszNewLocation = RTPathAbsDup(ValueUnion.psz); + fMoveMedium = true; + break; + + case 'l': // --setlocation + /* Get a new location */ + pszNewLocation = RTPathAbsDup(ValueUnion.psz); + fSetNewLocation = true; + break; + + case 'd': // --description + /* Get a new description */ + pszNewLocation = RTStrDup(ValueUnion.psz); + fModifyDescription = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszFilenameOrUuid) + pszFilenameOrUuid = ValueUnion.psz; + else + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Disk::tr("Invalid option -%c"), c); + else + return errorSyntax(Disk::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Disk::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Disk::tr("error: %Rrs"), c); + } + } + + if (cmd == CMD_NONE) + cmd = CMD_DISK; + + if (!pszFilenameOrUuid) + return errorSyntax(Disk::tr("Medium name or UUID required")); + + if (!fModifyMediumType + && !fModifyAutoReset + && !fModifyProperties + && !fModifyCompact + && !fModifyResize + && !fMoveMedium + && !fSetNewLocation + && !fModifyDescription + ) + return errorSyntax(Disk::tr("No operation specified")); + + /* Always open the medium if necessary, there is no other way. */ + if (cmd == CMD_DISK) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk, + AccessMode_ReadWrite, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_DVD) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD, + AccessMode_ReadOnly, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_FLOPPY) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy, + AccessMode_ReadWrite, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else + hrc = E_INVALIDARG; /* cannot happen but make gcc happy */ + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + if (pMedium.isNull()) + { + RTMsgError(Disk::tr("Invalid medium reference, avoiding crash")); + return RTEXITCODE_FAILURE; + } + + if ( fModifyResize + && fModifyResizeMB) + { + // Sanity check + // + // In general users should know what they do but in this case users have no + // alternative to VBoxManage. If happens that one wants to resize the disk + // and uses --resize and does not consider that this parameter expects the + // new medium size in MB not Byte. If the operation is started and then + // aborted by the user, the result is most likely a medium which doesn't + // work anymore. + MediumState_T state; + pMedium->RefreshState(&state); + LONG64 logicalSize; + pMedium->COMGETTER(LogicalSize)(&logicalSize); + if (cbResize > (uint64_t)logicalSize * 1000) + { + RTMsgError(Disk::tr("Error: Attempt to resize the medium from %RU64.%RU64 MB to %RU64.%RU64 MB. Use --resizebyte if this is intended!\n"), + logicalSize / _1M, (logicalSize % _1M) / (_1M / 10), cbResize / _1M, (cbResize % _1M) / (_1M / 10)); + return RTEXITCODE_FAILURE; + } + } + + if (fModifyMediumType) + { + MediumType_T enmCurrMediumType; + CHECK_ERROR(pMedium, COMGETTER(Type)(&enmCurrMediumType)); + + if (enmCurrMediumType != enmMediumType) + CHECK_ERROR(pMedium, COMSETTER(Type)(enmMediumType)); + } + + if (fModifyAutoReset) + { + CHECK_ERROR(pMedium, COMSETTER(AutoReset)(AutoReset)); + } + + if (fModifyProperties) + { + CHECK_ERROR(pMedium, SetProperties(ComSafeArrayAsInParam(mediumPropNames), ComSafeArrayAsInParam(mediumPropValues))); + } + + if (fModifyCompact) + { + ComPtr<IProgress> pProgress; + CHECK_ERROR(pMedium, Compact(pProgress.asOutParam())); + if (SUCCEEDED(hrc)) + hrc = showProgress(pProgress); + if (FAILED(hrc)) + { + if (hrc == E_NOTIMPL) + RTMsgError(Disk::tr("Compact medium operation is not implemented!")); + else if (hrc == VBOX_E_NOT_SUPPORTED) + RTMsgError(Disk::tr("Compact medium operation for this format is not implemented yet!")); + else if (!pProgress.isNull()) + CHECK_PROGRESS_ERROR(pProgress, (Disk::tr("Failed to compact medium"))); + else + RTMsgError(Disk::tr("Failed to compact medium!")); + } + } + + if (fModifyResize) + { + ComPtr<IProgress> pProgress; + CHECK_ERROR(pMedium, Resize(cbResize, pProgress.asOutParam())); + if (SUCCEEDED(hrc)) + hrc = showProgress(pProgress); + if (FAILED(hrc)) + { + if (!pProgress.isNull()) + CHECK_PROGRESS_ERROR(pProgress, (Disk::tr("Failed to resize medium"))); + else if (hrc == E_NOTIMPL) + RTMsgError(Disk::tr("Resize medium operation is not implemented!")); + else if (hrc == VBOX_E_NOT_SUPPORTED) + RTMsgError(Disk::tr("Resize medium operation for this format is not implemented yet!")); + else + RTMsgError(Disk::tr("Failed to resize medium!")); + } + } + + if (fMoveMedium) + { + do + { + ComPtr<IProgress> pProgress; + Utf8Str strLocation(pszNewLocation); + RTStrFree(pszNewLocation); + CHECK_ERROR(pMedium, MoveTo(Bstr(strLocation).raw(), pProgress.asOutParam())); + + if (SUCCEEDED(hrc) && !pProgress.isNull()) + { + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR(pProgress, (Disk::tr("Failed to move medium"))); + } + + Bstr uuid; + CHECK_ERROR_BREAK(pMedium, COMGETTER(Id)(uuid.asOutParam())); + + RTPrintf(Disk::tr("Move medium with UUID %s finished\n"), Utf8Str(uuid).c_str()); + } + while (0); + } + + if (fSetNewLocation) + { + Utf8Str strLocation(pszNewLocation); + RTStrFree(pszNewLocation); + CHECK_ERROR(pMedium, COMSETTER(Location)(Bstr(strLocation).raw())); + + Bstr uuid; + CHECK_ERROR(pMedium, COMGETTER(Id)(uuid.asOutParam())); + RTPrintf(Disk::tr("Set new location of medium with UUID %s finished\n"), Utf8Str(uuid).c_str()); + } + + if (fModifyDescription) + { + CHECK_ERROR(pMedium, COMSETTER(Description)(Bstr(pszNewLocation).raw())); + + RTPrintf(Disk::tr("Medium description has been changed.\n")); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aCloneMediumOptions[] = +{ + { "disk", 'd', RTGETOPT_REQ_NOTHING }, + { "dvd", 'D', RTGETOPT_REQ_NOTHING }, + { "floppy", 'f', RTGETOPT_REQ_NOTHING }, + { "--format", 'o', RTGETOPT_REQ_STRING }, + { "-format", 'o', RTGETOPT_REQ_STRING }, + { "--static", 'F', RTGETOPT_REQ_NOTHING }, + { "-static", 'F', RTGETOPT_REQ_NOTHING }, + { "--existing", 'E', RTGETOPT_REQ_NOTHING }, + { "--variant", 'm', RTGETOPT_REQ_STRING }, + { "-variant", 'm', RTGETOPT_REQ_STRING }, + { "--resize", 'r', RTGETOPT_REQ_UINT64 }, +}; + +RTEXITCODE handleCloneMedium(HandlerArg *a) +{ + HRESULT hrc; + int vrc; + enum { + CMD_NONE, + CMD_DISK, + CMD_DVD, + CMD_FLOPPY + } cmd = CMD_NONE; + const char *pszSrc = NULL; + const char *pszDst = NULL; + Bstr format; + MediumVariant_T enmMediumVariant = MediumVariant_Standard; + bool fExisting = false; + bool fNeedResize = false; + uint64_t cbResize = 0; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneMediumOptions, RT_ELEMENTS(g_aCloneMediumOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'd': // disk + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DISK; + break; + + case 'D': // DVD + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DVD; + break; + + case 'f': // floppy + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_FLOPPY; + break; + + case 'o': // --format + format = ValueUnion.psz; + break; + + case 'F': // --static + { + unsigned uMediumVariant = (unsigned)enmMediumVariant; + uMediumVariant |= MediumVariant_Fixed; + enmMediumVariant = (MediumVariant_T)uMediumVariant; + break; + } + + case 'E': // --existing + fExisting = true; + break; + + case 'm': // --variant + vrc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant); + if (RT_FAILURE(vrc)) + return errorArgument(Disk::tr("Invalid medium variant '%s'"), ValueUnion.psz); + break; + + case 'r': // --resize + fNeedResize = true; + cbResize = ValueUnion.u64 * _1M; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszSrc) + pszSrc = ValueUnion.psz; + else if (!pszDst) + pszDst = ValueUnion.psz; + else + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_GRAPH(c)) + return errorSyntax(Disk::tr("unhandled option: -%c"), c); + else + return errorSyntax(Disk::tr("unhandled option: %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Disk::tr("unknown option: %s"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Disk::tr("error: %Rrs"), c); + } + } + + if (cmd == CMD_NONE) + cmd = CMD_DISK; + if (!pszSrc) + return errorSyntax(Disk::tr("Mandatory UUID or input file parameter missing")); + if (!pszDst) + return errorSyntax(Disk::tr("Mandatory output file parameter missing")); + if (fExisting && (!format.isEmpty() || enmMediumVariant != MediumVariant_Standard)) + return errorSyntax(Disk::tr("Specified options which cannot be used with --existing")); + + ComPtr<IMedium> pSrcMedium; + ComPtr<IMedium> pDstMedium; + + if (cmd == CMD_DISK) + hrc = openMedium(a, pszSrc, DeviceType_HardDisk, AccessMode_ReadOnly, pSrcMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_DVD) + hrc = openMedium(a, pszSrc, DeviceType_DVD, AccessMode_ReadOnly, pSrcMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_FLOPPY) + hrc = openMedium(a, pszSrc, DeviceType_Floppy, AccessMode_ReadOnly, pSrcMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else + hrc = E_INVALIDARG; /* cannot happen but make gcc happy */ + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + do + { + /* open/create destination medium */ + if (fExisting) + { + if (cmd == CMD_DISK) + hrc = openMedium(a, pszDst, DeviceType_HardDisk, AccessMode_ReadWrite, pDstMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_DVD) + hrc = openMedium(a, pszDst, DeviceType_DVD, AccessMode_ReadOnly, pDstMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_FLOPPY) + hrc = openMedium(a, pszDst, DeviceType_Floppy, AccessMode_ReadWrite, pDstMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (FAILED(hrc)) + break; + + /* Perform accessibility check now. */ + MediumState_T state; + CHECK_ERROR_BREAK(pDstMedium, RefreshState(&state)); + CHECK_ERROR_BREAK(pDstMedium, COMGETTER(Format)(format.asOutParam())); + } + else + { + /* + * In case the format is unspecified check that the source medium supports + * image creation and use the same format for the destination image. + * Use the default image format if it is not supported. + */ + if (format.isEmpty()) + { + ComPtr<IMediumFormat> pMediumFmt; + com::SafeArray<MediumFormatCapabilities_T> l_caps; + CHECK_ERROR_BREAK(pSrcMedium, COMGETTER(MediumFormat)(pMediumFmt.asOutParam())); + CHECK_ERROR_BREAK(pMediumFmt, COMGETTER(Capabilities)(ComSafeArrayAsOutParam(l_caps))); + ULONG caps=0; + for (size_t i = 0; i < l_caps.size(); i++) + caps |= l_caps[i]; + if (caps & ( MediumFormatCapabilities_CreateDynamic + | MediumFormatCapabilities_CreateFixed)) + CHECK_ERROR_BREAK(pMediumFmt, COMGETTER(Id)(format.asOutParam())); + } + Utf8Str strFormat(format); + if (cmd == CMD_DISK) + hrc = createMedium(a, strFormat.c_str(), pszDst, DeviceType_HardDisk, + AccessMode_ReadWrite, pDstMedium); + else if (cmd == CMD_DVD) + hrc = createMedium(a, strFormat.c_str(), pszDst, DeviceType_DVD, + AccessMode_ReadOnly, pDstMedium); + else if (cmd == CMD_FLOPPY) + hrc = createMedium(a, strFormat.c_str(), pszDst, DeviceType_Floppy, + AccessMode_ReadWrite, pDstMedium); + if (FAILED(hrc)) + break; + } + + ComPtr<IProgress> pProgress; + com::SafeArray<MediumVariant_T> l_variants(sizeof(MediumVariant_T)*8); + + for (ULONG i = 0; i < l_variants.size(); ++i) + { + ULONG temp = enmMediumVariant; + temp &= 1<<i; + l_variants [i] = (MediumVariant_T)temp; + } + + if (fNeedResize) + { + CHECK_ERROR_BREAK(pSrcMedium, ResizeAndCloneTo(pDstMedium, cbResize, ComSafeArrayAsInParam(l_variants), NULL, pProgress.asOutParam())); + } + else + { + CHECK_ERROR_BREAK(pSrcMedium, CloneTo(pDstMedium, ComSafeArrayAsInParam(l_variants), NULL, pProgress.asOutParam())); + } + + + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR_BREAK(pProgress, (Disk::tr("Failed to clone medium"))); + + Bstr uuid; + CHECK_ERROR_BREAK(pDstMedium, COMGETTER(Id)(uuid.asOutParam())); + + RTPrintf(Disk::tr("Clone medium created in format '%ls'. UUID: %s\n"), + format.raw(), Utf8Str(uuid).c_str()); + } + while (0); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aConvertFromRawHardDiskOptions[] = +{ + { "--format", 'o', RTGETOPT_REQ_STRING }, + { "-format", 'o', RTGETOPT_REQ_STRING }, + { "--static", 'F', RTGETOPT_REQ_NOTHING }, + { "-static", 'F', RTGETOPT_REQ_NOTHING }, + { "--variant", 'm', RTGETOPT_REQ_STRING }, + { "-variant", 'm', RTGETOPT_REQ_STRING }, + { "--uuid", 'u', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleConvertFromRaw(HandlerArg *a) +{ + bool fReadFromStdIn = false; + const char *format = "VDI"; + const char *srcfilename = NULL; + const char *dstfilename = NULL; + const char *filesize = NULL; + unsigned uImageFlags = VD_IMAGE_FLAGS_NONE; + void *pvBuf = NULL; + RTUUID uuid; + PCRTUUID pUuid = NULL; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, + g_aConvertFromRawHardDiskOptions, RT_ELEMENTS(g_aConvertFromRawHardDiskOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'u': // --uuid + if (RT_FAILURE(RTUuidFromStr(&uuid, ValueUnion.psz))) + return errorSyntax(Disk::tr("Invalid UUID '%s'"), ValueUnion.psz); + pUuid = &uuid; + break; + case 'o': // --format + format = ValueUnion.psz; + break; + + case 'm': // --variant + { + MediumVariant_T enmMediumVariant = MediumVariant_Standard; + vrc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant); + if (RT_FAILURE(vrc)) + return errorArgument(Disk::tr("Invalid medium variant '%s'"), ValueUnion.psz); + /// @todo cleaner solution than assuming 1:1 mapping? + uImageFlags = (unsigned)enmMediumVariant; + break; + } + case VINF_GETOPT_NOT_OPTION: + if (!srcfilename) + { + srcfilename = ValueUnion.psz; + fReadFromStdIn = !strcmp(srcfilename, "stdin"); + } + else if (!dstfilename) + dstfilename = ValueUnion.psz; + else if (fReadFromStdIn && !filesize) + filesize = ValueUnion.psz; + else + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!srcfilename || !dstfilename || (fReadFromStdIn && !filesize)) + return errorSyntax(Disk::tr("Incorrect number of parameters")); + RTStrmPrintf(g_pStdErr, Disk::tr("Converting from raw image file=\"%s\" to file=\"%s\"...\n"), + srcfilename, dstfilename); + + PVDISK pDisk = NULL; + + PVDINTERFACE pVDIfs = NULL; + VDINTERFACEERROR vdInterfaceError; + vdInterfaceError.pfnError = handleVDError; + vdInterfaceError.pfnMessage = NULL; + + vrc = VDInterfaceAdd(&vdInterfaceError.Core, "VBoxManage_IError", VDINTERFACETYPE_ERROR, + NULL, sizeof(VDINTERFACEERROR), &pVDIfs); + AssertRC(vrc); + + /* open raw image file. */ + RTFILE File; + if (fReadFromStdIn) + vrc = RTFileFromNative(&File, RTFILE_NATIVE_STDIN); + else + vrc = RTFileOpen(&File, srcfilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_FAILURE(vrc)) + { + RTMsgError(Disk::tr("Cannot open file \"%s\": %Rrc"), srcfilename, vrc); + goto out; + } + + uint64_t cbFile; + /* get image size. */ + if (fReadFromStdIn) + cbFile = RTStrToUInt64(filesize); + else + vrc = RTFileQuerySize(File, &cbFile); + if (RT_FAILURE(vrc)) + { + RTMsgError(Disk::tr("Cannot get image size for file \"%s\": %Rrc"), srcfilename, vrc); + goto out; + } + + RTStrmPrintf(g_pStdErr, Disk::tr("Creating %s image with size %RU64 bytes (%RU64MB)...\n", "", cbFile), + (uImageFlags & VD_IMAGE_FLAGS_FIXED) ? Disk::tr("fixed", "adjective") : Disk::tr("dynamic", "adjective"), + cbFile, (cbFile + _1M - 1) / _1M); + char pszComment[256]; + RTStrPrintf(pszComment, sizeof(pszComment), Disk::tr("Converted image from %s"), srcfilename); + vrc = VDCreate(pVDIfs, VDTYPE_HDD, &pDisk); + if (RT_FAILURE(vrc)) + { + RTMsgError(Disk::tr("Cannot create the virtual disk container: %Rrc"), vrc); + goto out; + } + + Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) - + (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0); + VDGEOMETRY PCHS, LCHS; + PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383); + PCHS.cHeads = 16; + PCHS.cSectors = 63; + LCHS.cCylinders = 0; + LCHS.cHeads = 0; + LCHS.cSectors = 0; + vrc = VDCreateBase(pDisk, format, dstfilename, cbFile, + uImageFlags, pszComment, &PCHS, &LCHS, pUuid, + VD_OPEN_FLAGS_NORMAL, NULL, NULL); + if (RT_FAILURE(vrc)) + { + RTMsgError(Disk::tr("Cannot create the disk image \"%s\": %Rrc"), dstfilename, vrc); + goto out; + } + + size_t cbBuffer; + cbBuffer = _1M; + pvBuf = RTMemAlloc(cbBuffer); + if (!pvBuf) + { + vrc = VERR_NO_MEMORY; + RTMsgError(Disk::tr("Out of memory allocating buffers for image \"%s\": %Rrc"), dstfilename, vrc); + goto out; + } + + uint64_t offFile; + offFile = 0; + while (offFile < cbFile) + { + size_t cbRead; + size_t cbToRead; + cbRead = 0; + cbToRead = cbFile - offFile >= (uint64_t)cbBuffer ? + cbBuffer : (size_t)(cbFile - offFile); + vrc = RTFileRead(File, pvBuf, cbToRead, &cbRead); + if (RT_FAILURE(vrc) || !cbRead) + break; + vrc = VDWrite(pDisk, offFile, pvBuf, cbRead); + if (RT_FAILURE(vrc)) + { + RTMsgError(Disk::tr("Failed to write to disk image \"%s\": %Rrc"), dstfilename, vrc); + goto out; + } + offFile += cbRead; + } + +out: + if (pvBuf) + RTMemFree(pvBuf); + if (pDisk) + VDClose(pDisk, RT_FAILURE(vrc)); + if (File != NIL_RTFILE) + RTFileClose(File); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +HRESULT showMediumInfo(const ComPtr<IVirtualBox> &pVirtualBox, + const ComPtr<IMedium> &pMedium, + const char *pszParentUUID, + bool fOptLong) +{ + HRESULT hrc = S_OK; + do + { + Bstr uuid; + pMedium->COMGETTER(Id)(uuid.asOutParam()); + RTPrintf("UUID: %ls\n", uuid.raw()); + if (pszParentUUID) + RTPrintf(Disk::tr("Parent UUID: %s\n"), pszParentUUID); + + /* check for accessibility */ + MediumState_T enmState; + CHECK_ERROR_BREAK(pMedium, RefreshState(&enmState)); + const char *pszState = Disk::tr("unknown"); + switch (enmState) + { + case MediumState_NotCreated: + pszState = Disk::tr("not created"); + break; + case MediumState_Created: + pszState = Disk::tr("created"); + break; + case MediumState_LockedRead: + pszState = Disk::tr("locked read"); + break; + case MediumState_LockedWrite: + pszState = Disk::tr("locked write"); + break; + case MediumState_Inaccessible: + pszState = Disk::tr("inaccessible"); + break; + case MediumState_Creating: + pszState = Disk::tr("creating"); + break; + case MediumState_Deleting: + pszState = Disk::tr("deleting"); + break; +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case MediumState_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + RTPrintf(Disk::tr("State: %s\n"), pszState); + + if (fOptLong && enmState == MediumState_Inaccessible) + { + Bstr err; + CHECK_ERROR_BREAK(pMedium, COMGETTER(LastAccessError)(err.asOutParam())); + RTPrintf(Disk::tr("Access Error: %ls\n"), err.raw()); + } + + if (fOptLong) + { + Bstr description; + pMedium->COMGETTER(Description)(description.asOutParam()); + if (!description.isEmpty()) + RTPrintf(Disk::tr("Description: %ls\n"), description.raw()); + } + + MediumType_T type; + pMedium->COMGETTER(Type)(&type); + const char *typeStr = Disk::tr("unknown"); + switch (type) + { + case MediumType_Normal: + if (pszParentUUID && Guid(pszParentUUID).isValid()) + typeStr = Disk::tr("normal (differencing)"); + else + typeStr = Disk::tr("normal (base)"); + break; + case MediumType_Immutable: + typeStr = Disk::tr("immutable"); + break; + case MediumType_Writethrough: + typeStr = Disk::tr("writethrough"); + break; + case MediumType_Shareable: + typeStr = Disk::tr("shareable"); + break; + case MediumType_Readonly: + typeStr = Disk::tr("readonly"); + break; + case MediumType_MultiAttach: + typeStr = Disk::tr("multiattach"); + break; +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case MediumType_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + RTPrintf(Disk::tr("Type: %s\n"), typeStr); + + /* print out information specific for differencing media */ + if (fOptLong && pszParentUUID && Guid(pszParentUUID).isValid()) + { + BOOL autoReset = FALSE; + pMedium->COMGETTER(AutoReset)(&autoReset); + RTPrintf(Disk::tr("Auto-Reset: %s\n"), autoReset ? Disk::tr("on") : Disk::tr("off")); + } + + Bstr loc; + pMedium->COMGETTER(Location)(loc.asOutParam()); + RTPrintf(Disk::tr("Location: %ls\n"), loc.raw()); + + Bstr format; + pMedium->COMGETTER(Format)(format.asOutParam()); + RTPrintf(Disk::tr("Storage format: %ls\n"), format.raw()); + + if (fOptLong) + { + com::SafeArray<MediumVariant_T> safeArray_variant; + + pMedium->COMGETTER(Variant)(ComSafeArrayAsOutParam(safeArray_variant)); + ULONG variant=0; + for (size_t i = 0; i < safeArray_variant.size(); i++) + variant |= safeArray_variant[i]; + + const char *variantStr = Disk::tr("unknown"); + switch (variant & ~(MediumVariant_Fixed | MediumVariant_Diff)) + { + case MediumVariant_VmdkSplit2G: + variantStr = Disk::tr("split2G"); + break; + case MediumVariant_VmdkStreamOptimized: + variantStr = Disk::tr("streamOptimized"); + break; + case MediumVariant_VmdkESX: + variantStr = Disk::tr("ESX"); + break; + case MediumVariant_Standard: + variantStr = Disk::tr("default"); + break; + } + const char *variantTypeStr = Disk::tr("dynamic"); + if (variant & MediumVariant_Fixed) + variantTypeStr = Disk::tr("fixed"); + else if (variant & MediumVariant_Diff) + variantTypeStr = Disk::tr("differencing"); + RTPrintf(Disk::tr("Format variant: %s %s\n"), variantTypeStr, variantStr); + } + + LONG64 logicalSize; + pMedium->COMGETTER(LogicalSize)(&logicalSize); + RTPrintf(Disk::tr("Capacity: %lld MBytes\n"), logicalSize >> 20); + if (fOptLong) + { + LONG64 actualSize; + pMedium->COMGETTER(Size)(&actualSize); + RTPrintf(Disk::tr("Size on disk: %lld MBytes\n"), actualSize >> 20); + } + + Bstr strCipher; + Bstr strPasswordId; + HRESULT hrc2 = pMedium->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam()); + if (SUCCEEDED(hrc2)) + { + RTPrintf(Disk::tr("Encryption: enabled\n")); + if (fOptLong) + { + RTPrintf(Disk::tr("Cipher: %ls\n"), strCipher.raw()); + RTPrintf(Disk::tr("Password ID: %ls\n"), strPasswordId.raw()); + } + } + else + RTPrintf(Disk::tr("Encryption: disabled\n")); + + if (fOptLong) + { + com::SafeArray<BSTR> names; + com::SafeArray<BSTR> values; + pMedium->GetProperties(Bstr().raw(), ComSafeArrayAsOutParam(names), ComSafeArrayAsOutParam(values)); + size_t cNames = names.size(); + size_t cValues = values.size(); + bool fFirst = true; + for (size_t i = 0; i < cNames; i++) + { + Bstr value; + if (i < cValues) + value = values[i]; + RTPrintf("%s%ls=%ls\n", + fFirst ? Disk::tr("Property: ") : " ", + names[i], value.raw()); + fFirst = false; + } + } + + if (fOptLong) + { + bool fFirst = true; + com::SafeArray<BSTR> machineIds; + pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds)); + for (size_t i = 0; i < machineIds.size(); i++) + { + ComPtr<IMachine> pMachine; + CHECK_ERROR(pVirtualBox, FindMachine(machineIds[i], pMachine.asOutParam())); + if (pMachine) + { + Bstr name; + pMachine->COMGETTER(Name)(name.asOutParam()); + pMachine->COMGETTER(Id)(uuid.asOutParam()); + RTPrintf("%s%ls (UUID: %ls)", + fFirst ? Disk::tr("In use by VMs: ") : " ", + name.raw(), machineIds[i]); + fFirst = false; + com::SafeArray<BSTR> snapshotIds; + pMedium->GetSnapshotIds(machineIds[i], + ComSafeArrayAsOutParam(snapshotIds)); + for (size_t j = 0; j < snapshotIds.size(); j++) + { + ComPtr<ISnapshot> pSnapshot; + pMachine->FindSnapshot(snapshotIds[j], pSnapshot.asOutParam()); + if (pSnapshot) + { + Bstr snapshotName; + pSnapshot->COMGETTER(Name)(snapshotName.asOutParam()); + RTPrintf(" [%ls (UUID: %ls)]", snapshotName.raw(), snapshotIds[j]); + } + } + RTPrintf("\n"); + } + } + } + + if (fOptLong) + { + com::SafeIfaceArray<IMedium> children; + pMedium->COMGETTER(Children)(ComSafeArrayAsOutParam(children)); + bool fFirst = true; + for (size_t i = 0; i < children.size(); i++) + { + ComPtr<IMedium> pChild(children[i]); + if (pChild) + { + Bstr childUUID; + pChild->COMGETTER(Id)(childUUID.asOutParam()); + RTPrintf("%s%ls\n", + fFirst ? Disk::tr("Child UUIDs: ") : " ", + childUUID.raw()); + fFirst = false; + } + } + } + } + while (0); + + return hrc; +} + +static const RTGETOPTDEF g_aShowMediumInfoOptions[] = +{ + { "disk", 'd', RTGETOPT_REQ_NOTHING }, + { "dvd", 'D', RTGETOPT_REQ_NOTHING }, + { "floppy", 'f', RTGETOPT_REQ_NOTHING }, +}; + +RTEXITCODE handleShowMediumInfo(HandlerArg *a) +{ + enum { + CMD_NONE, + CMD_DISK, + CMD_DVD, + CMD_FLOPPY + } cmd = CMD_NONE; + const char *pszFilenameOrUuid = NULL; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aShowMediumInfoOptions, RT_ELEMENTS(g_aShowMediumInfoOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'd': // disk + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DISK; + break; + + case 'D': // DVD + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DVD; + break; + + case 'f': // floppy + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_FLOPPY; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszFilenameOrUuid) + pszFilenameOrUuid = ValueUnion.psz; + else + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Disk::tr("Invalid option -%c"), c); + else + return errorSyntax(Disk::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Disk::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Disk::tr("error: %Rrs"), c); + } + } + + if (cmd == CMD_NONE) + cmd = CMD_DISK; + + /* check for required options */ + if (!pszFilenameOrUuid) + return errorSyntax(Disk::tr("Medium name or UUID required")); + + HRESULT hrc = S_OK; /* Prevents warning. */ + + ComPtr<IMedium> pMedium; + if (cmd == CMD_DISK) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk, + AccessMode_ReadOnly, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_DVD) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD, + AccessMode_ReadOnly, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_FLOPPY) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy, + AccessMode_ReadOnly, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + Utf8Str strParentUUID(Disk::tr("base")); + ComPtr<IMedium> pParent; + pMedium->COMGETTER(Parent)(pParent.asOutParam()); + if (!pParent.isNull()) + { + Bstr bstrParentUUID; + pParent->COMGETTER(Id)(bstrParentUUID.asOutParam()); + strParentUUID = bstrParentUUID; + } + + hrc = showMediumInfo(a->virtualBox, pMedium, strParentUUID.c_str(), true); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aCloseMediumOptions[] = +{ + { "disk", 'd', RTGETOPT_REQ_NOTHING }, + { "dvd", 'D', RTGETOPT_REQ_NOTHING }, + { "floppy", 'f', RTGETOPT_REQ_NOTHING }, + { "--delete", 'r', RTGETOPT_REQ_NOTHING }, +}; + +RTEXITCODE handleCloseMedium(HandlerArg *a) +{ + HRESULT hrc = S_OK; + enum { + CMD_NONE, + CMD_DISK, + CMD_DVD, + CMD_FLOPPY + } cmd = CMD_NONE; + const char *pszFilenameOrUuid = NULL; + bool fDelete = false; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aCloseMediumOptions, RT_ELEMENTS(g_aCloseMediumOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'd': // disk + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DISK; + break; + + case 'D': // DVD + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_DVD; + break; + + case 'f': // floppy + if (cmd != CMD_NONE) + return errorSyntax(Disk::tr("Only one command can be specified: '%s'"), ValueUnion.psz); + cmd = CMD_FLOPPY; + break; + + case 'r': // --delete + fDelete = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszFilenameOrUuid) + pszFilenameOrUuid = ValueUnion.psz; + else + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Disk::tr("Invalid option -%c"), c); + else + return errorSyntax(Disk::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Disk::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Disk::tr("error: %Rrs"), c); + } + } + + /* check for required options */ + if (cmd == CMD_NONE) + cmd = CMD_DISK; + if (!pszFilenameOrUuid) + return errorSyntax(Disk::tr("Medium name or UUID required")); + + ComPtr<IMedium> pMedium; + if (cmd == CMD_DISK) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk, + AccessMode_ReadWrite, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_DVD) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD, + AccessMode_ReadOnly, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_FLOPPY) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy, + AccessMode_ReadWrite, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + + if (SUCCEEDED(hrc) && pMedium) + { + if (fDelete) + { + ComPtr<IProgress> pProgress; + CHECK_ERROR(pMedium, DeleteStorage(pProgress.asOutParam())); + if (SUCCEEDED(hrc)) + { + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR(pProgress, (Disk::tr("Failed to delete medium"))); + } + else + RTMsgError(Disk::tr("Failed to delete medium. Error code %Rhrc"), hrc); + } + CHECK_ERROR(pMedium, Close()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleMediumProperty(HandlerArg *a) +{ + HRESULT hrc = S_OK; + const char *pszCmd = NULL; + enum { + CMD_NONE, + CMD_DISK, + CMD_DVD, + CMD_FLOPPY + } cmd = CMD_NONE; + const char *pszAction = NULL; + const char *pszFilenameOrUuid = NULL; + const char *pszProperty = NULL; + ComPtr<IMedium> pMedium; + + pszCmd = (a->argc > 0) ? a->argv[0] : ""; + if ( !RTStrICmp(pszCmd, "disk") + || !RTStrICmp(pszCmd, "dvd") + || !RTStrICmp(pszCmd, "floppy")) + { + if (!RTStrICmp(pszCmd, "disk")) + cmd = CMD_DISK; + else if (!RTStrICmp(pszCmd, "dvd")) + cmd = CMD_DVD; + else if (!RTStrICmp(pszCmd, "floppy")) + cmd = CMD_FLOPPY; + else + { + AssertMsgFailed((Disk::tr("unexpected parameter %s\n"), pszCmd)); + cmd = CMD_DISK; + } + a->argv++; + a->argc--; + } + else + { + pszCmd = NULL; + cmd = CMD_DISK; + } + + if (a->argc == 0) + return errorSyntax(Disk::tr("Missing action")); + + pszAction = a->argv[0]; + if ( RTStrICmp(pszAction, "set") + && RTStrICmp(pszAction, "get") + && RTStrICmp(pszAction, "delete")) + return errorSyntax(Disk::tr("Invalid action given: %s"), pszAction); + + if ( ( !RTStrICmp(pszAction, "set") + && a->argc != 4) + || ( RTStrICmp(pszAction, "set") + && a->argc != 3)) + return errorSyntax(Disk::tr("Invalid number of arguments given for action: %s"), pszAction); + + pszFilenameOrUuid = a->argv[1]; + pszProperty = a->argv[2]; + + if (cmd == CMD_DISK) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk, + AccessMode_ReadWrite, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_DVD) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_DVD, + AccessMode_ReadOnly, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + else if (cmd == CMD_FLOPPY) + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_Floppy, + AccessMode_ReadWrite, pMedium, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (SUCCEEDED(hrc) && !pMedium.isNull()) + { + if (!RTStrICmp(pszAction, "set")) + { + const char *pszValue = a->argv[3]; + CHECK_ERROR(pMedium, SetProperty(Bstr(pszProperty).raw(), Bstr(pszValue).raw())); + } + else if (!RTStrICmp(pszAction, "get")) + { + /* + * Trigger a call to Medium::i_queryInfo()->VDOpen()->pfnOpen() to + * open the virtual device and populate its properties for + * Medium::getProperty() to retrieve. + */ + MediumState_T state; + CHECK_ERROR(pMedium, RefreshState(&state)); + + Bstr strVal; + CHECK_ERROR(pMedium, GetProperty(Bstr(pszProperty).raw(), strVal.asOutParam())); + if (SUCCEEDED(hrc)) + RTPrintf("%s=%ls\n", pszProperty, strVal.raw()); + } + else if (!RTStrICmp(pszAction, "delete")) + { + CHECK_ERROR(pMedium, SetProperty(Bstr(pszProperty).raw(), Bstr().raw())); + /** @todo */ + } + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aEncryptMediumOptions[] = +{ + { "--newpassword", 'n', RTGETOPT_REQ_STRING }, + { "--oldpassword", 'o', RTGETOPT_REQ_STRING }, + { "--cipher", 'c', RTGETOPT_REQ_STRING }, + { "--newpasswordid", 'i', RTGETOPT_REQ_STRING } +}; + +RTEXITCODE handleEncryptMedium(HandlerArg *a) +{ + HRESULT hrc; + ComPtr<IMedium> hardDisk; + const char *pszPasswordNew = NULL; + const char *pszPasswordOld = NULL; + const char *pszCipher = NULL; + const char *pszFilenameOrUuid = NULL; + const char *pszNewPasswordId = NULL; + Utf8Str strPasswordNew; + Utf8Str strPasswordOld; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aEncryptMediumOptions, RT_ELEMENTS(g_aEncryptMediumOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'n': // --newpassword + pszPasswordNew = ValueUnion.psz; + break; + + case 'o': // --oldpassword + pszPasswordOld = ValueUnion.psz; + break; + + case 'c': // --cipher + pszCipher = ValueUnion.psz; + break; + + case 'i': // --newpasswordid + pszNewPasswordId = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszFilenameOrUuid) + pszFilenameOrUuid = ValueUnion.psz; + else + return errorSyntax(Disk::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Disk::tr("Invalid option -%c"), c); + else + return errorSyntax(Disk::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Disk::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Disk::tr("error: %Rrs"), c); + } + } + + if (!pszFilenameOrUuid) + return errorSyntax(Disk::tr("Disk name or UUID required")); + + if (!pszPasswordNew && !pszPasswordOld) + return errorSyntax(Disk::tr("No password specified")); + + if ( (pszPasswordNew && !pszNewPasswordId) + || (!pszPasswordNew && pszNewPasswordId)) + return errorSyntax(Disk::tr("A new password must always have a valid identifier set at the same time")); + + if (pszPasswordNew) + { + if (!RTStrCmp(pszPasswordNew, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordNew, Disk::tr("Enter new password:")); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPasswordNew, &strPasswordNew); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError(Disk::tr("Failed to read new password from file")); + return rcExit; + } + } + } + + if (pszPasswordOld) + { + if (!RTStrCmp(pszPasswordOld, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordOld, Disk::tr("Enter old password:")); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPasswordOld, &strPasswordOld); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError(Disk::tr("Failed to read old password from file")); + return rcExit; + } + } + } + + /* Always open the medium if necessary, there is no other way. */ + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk, + AccessMode_ReadWrite, hardDisk, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + if (hardDisk.isNull()) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Disk::tr("Invalid hard disk reference, avoiding crash")); + + ComPtr<IProgress> progress; + CHECK_ERROR(hardDisk, ChangeEncryption(Bstr(strPasswordOld).raw(), Bstr(pszCipher).raw(), + Bstr(strPasswordNew).raw(), Bstr(pszNewPasswordId).raw(), + progress.asOutParam())); + if (SUCCEEDED(hrc)) + hrc = showProgress(progress); + if (FAILED(hrc)) + { + if (hrc == E_NOTIMPL) + RTMsgError(Disk::tr("Encrypt hard disk operation is not implemented!")); + else if (hrc == VBOX_E_NOT_SUPPORTED) + RTMsgError(Disk::tr("Encrypt hard disk operation for this cipher is not implemented yet!")); + else if (!progress.isNull()) + CHECK_PROGRESS_ERROR(progress, (Disk::tr("Failed to encrypt hard disk"))); + else + RTMsgError(Disk::tr("Failed to encrypt hard disk!")); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleCheckMediumPassword(HandlerArg *a) +{ + HRESULT hrc; + ComPtr<IMedium> hardDisk; + const char *pszFilenameOrUuid = NULL; + Utf8Str strPassword; + + if (a->argc != 2) + return errorSyntax(Disk::tr("Invalid number of arguments: %d"), a->argc); + + pszFilenameOrUuid = a->argv[0]; + + if (!RTStrCmp(a->argv[1], "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, Disk::tr("Enter password:")); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(a->argv[1], &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError(Disk::tr("Failed to read password from file")); + return rcExit; + } + } + + /* Always open the medium if necessary, there is no other way. */ + hrc = openMedium(a, pszFilenameOrUuid, DeviceType_HardDisk, + AccessMode_ReadWrite, hardDisk, + false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + if (hardDisk.isNull()) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Disk::tr("Invalid hard disk reference, avoiding crash")); + + CHECK_ERROR(hardDisk, CheckEncryptionPassword(Bstr(strPassword).raw())); + if (SUCCEEDED(hrc)) + RTPrintf(Disk::tr("The given password is correct\n")); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/********************************************************************************************************************************* +* The mediumio command * +*********************************************************************************************************************************/ + +/** + * Common MediumIO options. + */ +typedef struct MEDIUMIOCOMMONOPT +{ + const char *pszFilenameOrUuid; + DeviceType_T enmDeviceType; + const char *pszPasswordFile; +} MEDIUMIOCOMMONOPT; +typedef MEDIUMIOCOMMONOPT *PMEDIUMIOCOMMONOPT; +typedef MEDIUMIOCOMMONOPT const *PCMEDIUMIOCOMMONOPT; + +/* For RTGETOPTDEF array initializer. */ +#define MEDIUMIOCOMMONOPT_DEFS() \ + { "--disk", 'd', RTGETOPT_REQ_STRING }, \ + { "--harddisk", 'd', RTGETOPT_REQ_STRING }, \ + { "disk", 'd', RTGETOPT_REQ_STRING }, \ + { "harddisk", 'd', RTGETOPT_REQ_STRING }, \ + { "--dvd", 'D', RTGETOPT_REQ_STRING }, \ + { "--iso", 'D', RTGETOPT_REQ_STRING }, \ + { "dvd", 'D', RTGETOPT_REQ_STRING }, \ + { "iso", 'D', RTGETOPT_REQ_STRING }, \ + { "--floppy", 'f', RTGETOPT_REQ_STRING }, \ + { "floppy", 'f', RTGETOPT_REQ_STRING }, \ + { "--password-file", 'P', RTGETOPT_REQ_STRING } + +/* For option switch. */ +#define MEDIUMIOCOMMONOPT_CASES(a_pCommonOpts) \ + case 'd': \ + (a_pCommonOpts)->enmDeviceType = DeviceType_HardDisk; \ + (a_pCommonOpts)->pszFilenameOrUuid = ValueUnion.psz; \ + break; \ + case 'D': \ + (a_pCommonOpts)->enmDeviceType = DeviceType_DVD; \ + (a_pCommonOpts)->pszFilenameOrUuid = ValueUnion.psz; \ + break; \ + case 'f': \ + (a_pCommonOpts)->enmDeviceType = DeviceType_Floppy; \ + (a_pCommonOpts)->pszFilenameOrUuid = ValueUnion.psz; \ + break; \ + case 'P': \ + (a_pCommonOpts)->pszPasswordFile = ValueUnion.psz; \ + break + + +/** + * Worker for mediumio operations that returns a IMediumIO for the specified + * medium. + * + * @returns Exit code. + * @param pHandler The handler state structure (for IVirtualBox). + * @param pCommonOpts Common mediumio options. + * @param fWritable Whether to open writable (true) or read only + * (false). + * @param rPtrMediumIO Where to return the IMediumIO pointer. + * @param pcbMedium Where to return the meidum size. Optional. + */ +static RTEXITCODE mediumIOOpenMediumForIO(HandlerArg *pHandler, PCMEDIUMIOCOMMONOPT pCommonOpts, bool fWritable, + ComPtr<IMediumIO> &rPtrMediumIO, uint64_t *pcbMedium = NULL) +{ + /* Clear returns. */ + if (pcbMedium) + *pcbMedium = 0; + rPtrMediumIO.setNull(); + + /* + * Make sure a medium was specified already. + */ + if (pCommonOpts->enmDeviceType == DeviceType_Null) + return errorSyntax(Disk::tr("No medium specified!")); + + /* + * Read the password. + */ + Bstr bstrPassword; + if (pCommonOpts->pszPasswordFile) + { + Utf8Str strPassword; + RTEXITCODE rcExit; + if (pCommonOpts->pszPasswordFile[0] == '-' && pCommonOpts->pszPasswordFile[1] == '\0') + rcExit = readPasswordFromConsole(&strPassword, Disk::tr("Enter encryption password:")); + else + rcExit = readPasswordFile(pCommonOpts->pszPasswordFile, &strPassword); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + bstrPassword = strPassword; + strPassword.assign(strPassword.length(), '*'); + } + + /* + * Open the medium and then get I/O access to it. + */ + ComPtr<IMedium> ptrMedium; + HRESULT hrc = openMedium(pHandler, pCommonOpts->pszFilenameOrUuid, pCommonOpts->enmDeviceType, + fWritable ? AccessMode_ReadWrite : AccessMode_ReadOnly, + ptrMedium, false /* fForceNewUuidOnOpen */, false /* fSilent */); + if (SUCCEEDED(hrc)) + { + CHECK_ERROR2I_STMT(ptrMedium, OpenForIO(fWritable, bstrPassword.raw(), rPtrMediumIO.asOutParam()), hrc = hrcCheck); + + /* + * If the size is requested get it after we've opened it. + */ + if (pcbMedium && SUCCEEDED(hrc)) + { + LONG64 cbLogical = 0; + CHECK_ERROR2I_STMT(ptrMedium, COMGETTER(LogicalSize)(&cbLogical), hrc = hrcCheck); + *pcbMedium = cbLogical; + if (!SUCCEEDED(hrc)) + rPtrMediumIO.setNull(); + } + } + + if (bstrPassword.isNotEmpty()) + memset(bstrPassword.mutableRaw(), '*', bstrPassword.length() * sizeof(RTUTF16)); + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +/** + * mediumio formatfat + */ +static RTEXITCODE handleMediumIOFormatFat(HandlerArg *a, int iFirst, PMEDIUMIOCOMMONOPT pCommonOpts) +{ + /* + * Parse the options. + */ + bool fQuick = false; + static const RTGETOPTDEF s_aOptions[] = + { + MEDIUMIOCOMMONOPT_DEFS(), + { "--quick", 'q', RTGETOPT_REQ_NOTHING }, + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + MEDIUMIOCOMMONOPT_CASES(pCommonOpts); + + case 'q': + fQuick = true; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Open the medium for I/O and format it. + */ + ComPtr<IMediumIO> ptrMediumIO; + RTEXITCODE rcExit = mediumIOOpenMediumForIO(a, pCommonOpts, true /*fWritable*/, ptrMediumIO); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + CHECK_ERROR2I_RET(ptrMediumIO, FormatFAT(fQuick), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + +/** + * mediumio cat + */ +static RTEXITCODE handleMediumIOCat(HandlerArg *a, int iFirst, PMEDIUMIOCOMMONOPT pCommonOpts) +{ + /* + * Parse the options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + MEDIUMIOCOMMONOPT_DEFS(), + { "--hex", 'H', RTGETOPT_REQ_NOTHING }, + { "--offset", 'o', RTGETOPT_REQ_UINT64 }, + { "--output", 'O', RTGETOPT_REQ_STRING }, + { "--size", 's', RTGETOPT_REQ_UINT64 }, + }; + bool fHex = false; + uint64_t off = 0; + const char *pszOutput = NULL; + uint64_t cb = UINT64_MAX; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + MEDIUMIOCOMMONOPT_CASES(pCommonOpts); + + case 'H': + fHex = true; + break; + + case 'o': + off = ValueUnion.u64; + break; + + case 'O': + pszOutput = ValueUnion.psz; + break; + + case 's': + cb = ValueUnion.u64; + break; + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Open the medium for I/O. + */ + ComPtr<IMediumIO> ptrMediumIO; + uint64_t cbMedium; + RTEXITCODE rcExit = mediumIOOpenMediumForIO(a, pCommonOpts, false /*fWritable*/, ptrMediumIO, &cbMedium); + if (rcExit == RTEXITCODE_SUCCESS) + { + /* + * Do we have an output file or do we write to stdout? + */ + PRTSTREAM pOut = NULL; + if (pszOutput && (pszOutput[0] != '-' || pszOutput[1] != '\0')) + { + vrc = RTStrmOpen(pszOutput, fHex ? "wt" : "wb", &pOut); + if (RT_FAILURE(vrc)) + rcExit = RTMsgErrorExitFailure(Disk::tr("Error opening '%s' for writing: %Rrc"), pszOutput, vrc); + } + else + { + pOut = g_pStdOut; + if (!fHex) + RTStrmSetMode(pOut, true, -1); + } + + if (rcExit == RTEXITCODE_SUCCESS) + { + /* + * Adjust 'cb' now that we've got the medium size. + */ + if (off >= cbMedium) + { + RTMsgWarning(Disk::tr("Specified offset (%#RX64) is beyond the end of the medium (%#RX64)"), off, cbMedium); + cb = 0; + } + else if ( cb > cbMedium + || cb + off > cbMedium) + cb = cbMedium - off; + + /* + * Hex dump preps. (The duplication detection is making ASSUMPTIONS about + * all the reads being a multiple of cchWidth, except for the final one.) + */ + char abHexBuf[16] = { 0 }; + size_t cbHexBuf = 0; + unsigned const cchWidth = RT_ELEMENTS(abHexBuf); + uint64_t const offEndDupCheck = cb - cchWidth; + uint64_t cDuplicates = 0; + + /* + * Do the reading. + */ + while (cb > 0) + { + char szLine[32 + cchWidth * 4 + 32]; + + /* Do the reading. */ + uint32_t const cbToRead = (uint32_t)RT_MIN(cb, _128K); + SafeArray<BYTE> SafeArrayBuf; + HRESULT hrc = ptrMediumIO->Read(off, cbToRead, ComSafeArrayAsOutParam(SafeArrayBuf)); + if (FAILED(hrc)) + { + RTStrPrintf(szLine, sizeof(szLine), Disk::tr("Read(%zu bytes at %#RX64)", "", cbToRead), cbToRead, off); + com::GlueHandleComError(ptrMediumIO, szLine, hrc, __FILE__, __LINE__); + break; + } + + /* Output the data. */ + size_t const cbReturned = SafeArrayBuf.size(); + if (cbReturned) + { + BYTE const *pbBuf = SafeArrayBuf.raw(); + if (!fHex) + vrc = RTStrmWrite(pOut, pbBuf, cbReturned); + else + { + /* hexdump -C */ + vrc = VINF_SUCCESS; + uint64_t offHex = off; + uint64_t const offHexEnd = off + cbReturned; + while (offHex < offHexEnd) + { + if ( offHex >= offEndDupCheck + || cbHexBuf == 0 + || memcmp(pbBuf, abHexBuf, cchWidth) != 0 + || ( cDuplicates == 0 + && ( offHex + cchWidth >= offEndDupCheck + || memcmp(pbBuf + cchWidth, pbBuf, cchWidth) != 0)) ) + { + if (cDuplicates > 0) + { + RTStrmPrintf(pOut, Disk::tr("********** <ditto x %RU64>\n"), cDuplicates); + cDuplicates = 0; + } + + size_t cch = RTStrPrintf(szLine, sizeof(szLine), "%012RX64:", offHex); + unsigned i; + for (i = 0; i < cchWidth && offHex + i < offHexEnd; i++) + { + static const char s_szHexDigits[17] = "0123456789abcdef"; + szLine[cch++] = (i & 7) || i == 0 ? ' ' : '-'; + uint8_t const u8 = pbBuf[i]; + szLine[cch++] = s_szHexDigits[u8 >> 4]; + szLine[cch++] = s_szHexDigits[u8 & 0xf]; + } + while (i++ < cchWidth) + { + szLine[cch++] = ' '; + szLine[cch++] = ' '; + szLine[cch++] = ' '; + } + szLine[cch++] = ' '; + + for (i = 0; i < cchWidth && offHex + i < offHexEnd; i++) + { + uint8_t const u8 = pbBuf[i]; + szLine[cch++] = u8 < 127 && u8 >= 32 ? u8 : '.'; + } + szLine[cch++] = '\n'; + szLine[cch] = '\0'; + + vrc = RTStrmWrite(pOut, szLine, cch); + if (RT_FAILURE(vrc)) + break; + + + /* copy bytes over to the duplication detection buffer. */ + cbHexBuf = (size_t)RT_MIN(cchWidth, offHexEnd - offHex); + memcpy(abHexBuf, pbBuf, cbHexBuf); + } + else + cDuplicates++; + + /* Advance to next line. */ + pbBuf += cchWidth; + offHex += cchWidth; + } + } + if (RT_FAILURE(vrc)) + { + rcExit = RTMsgErrorExitFailure(Disk::tr("Error writing to '%s': %Rrc"), pszOutput, vrc); + break; + } + } + + /* Advance. */ + if (cbReturned != cbToRead) + { + rcExit = RTMsgErrorExitFailure(Disk::tr("Expected read() at offset %RU64 (%#RX64) to return %#zx bytes, only got %#zx!\n", + "", cbReturned), + off, off, cbReturned, cbToRead); + break; + } + off += cbReturned; + cb -= cbReturned; + } + + /* + * Close output. + */ + if (pOut != g_pStdOut) + { + vrc = RTStrmClose(pOut); + if (RT_FAILURE(vrc)) + rcExit = RTMsgErrorExitFailure(Disk::tr("Error closing '%s': %Rrc"), pszOutput, vrc); + } + else if (!fHex) + RTStrmSetMode(pOut, false, -1); + } + } + return rcExit; +} + +/** + * mediumio stream + */ +static RTEXITCODE handleMediumIOStream(HandlerArg *a, int iFirst, PMEDIUMIOCOMMONOPT pCommonOpts) +{ + /* + * Parse the options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + MEDIUMIOCOMMONOPT_DEFS(), + { "--output", 'O', RTGETOPT_REQ_STRING }, + { "--format", 'F', RTGETOPT_REQ_STRING }, + { "--variant", 'v', RTGETOPT_REQ_STRING } + }; + const char *pszOutput = NULL; + MediumVariant_T enmMediumVariant = MediumVariant_Standard; + Bstr strFormat; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + MEDIUMIOCOMMONOPT_CASES(pCommonOpts); + + case 'O': + pszOutput = ValueUnion.psz; + break; + case 'F': + strFormat = ValueUnion.psz; + break; + case 'v': // --variant + { + vrc = parseMediumVariant(ValueUnion.psz, &enmMediumVariant); + if (RT_FAILURE(vrc)) + return errorArgument(Disk::tr("Invalid medium variant '%s'"), ValueUnion.psz); + break; + } + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + /* + * Open the medium for I/O. + */ + ComPtr<IMediumIO> ptrMediumIO; + uint64_t cbMedium; + RTEXITCODE rcExit = mediumIOOpenMediumForIO(a, pCommonOpts, false /*fWritable*/, ptrMediumIO, &cbMedium); + if (rcExit == RTEXITCODE_SUCCESS) + { + /* + * Do we have an output file or do we write to stdout? + */ + PRTSTREAM pOut = NULL; + if (pszOutput && (pszOutput[0] != '-' || pszOutput[1] != '\0')) + { + vrc = RTStrmOpen(pszOutput, "wb", &pOut); + if (RT_FAILURE(vrc)) + rcExit = RTMsgErrorExitFailure(Disk::tr("Error opening '%s' for writing: %Rrc"), pszOutput, vrc); + } + else + { + pOut = g_pStdOut; + RTStrmSetMode(pOut, true, -1); + } + + if (rcExit == RTEXITCODE_SUCCESS) + { + ComPtr<IDataStream> ptrDataStream; + ComPtr<IProgress> ptrProgress; + + com::SafeArray<MediumVariant_T> l_variants(sizeof(MediumVariant_T)*8); + + for (ULONG i = 0; i < l_variants.size(); ++i) + { + ULONG temp = enmMediumVariant; + temp &= 1<<i; + l_variants [i] = (MediumVariant_T)temp; + } + + HRESULT hrc = ptrMediumIO->ConvertToStream(strFormat.raw(), ComSafeArrayAsInParam(l_variants), 10 * _1M, ptrDataStream.asOutParam(), ptrProgress.asOutParam()); + if (hrc == S_OK) + { + /* Read until we reached the end of the stream. */ + for (;;) + { + SafeArray<BYTE> SafeArrayBuf; + + hrc = ptrDataStream->Read(_64K, 0 /*Infinite wait*/, ComSafeArrayAsOutParam(SafeArrayBuf)); + if ( FAILED(hrc) + || SafeArrayBuf.size() == 0) + break; + + /* Output the data. */ + size_t const cbReturned = SafeArrayBuf.size(); + if (cbReturned) + { + BYTE const *pbBuf = SafeArrayBuf.raw(); + vrc = RTStrmWrite(pOut, pbBuf, cbReturned); + if (RT_FAILURE(vrc)) + { + rcExit = RTMsgErrorExitFailure(Disk::tr("Error writing to '%s': %Rrc"), pszOutput, vrc); + break; + } + } + + /** @todo Check progress. */ + } + } + else + { + com::GlueHandleComError(ptrMediumIO, "ConvertToStream()", hrc, __FILE__, __LINE__); + rcExit = RTEXITCODE_FAILURE; + } + + /* + * Close output. + */ + if (pOut != g_pStdOut) + { + vrc = RTStrmClose(pOut); + if (RT_FAILURE(vrc)) + rcExit = RTMsgErrorExitFailure(Disk::tr("Error closing '%s': %Rrc"), pszOutput, vrc); + } + else + RTStrmSetMode(pOut, false, -1); + } + } + return rcExit; +} + + +RTEXITCODE handleMediumIO(HandlerArg *a) +{ + /* + * Parse image-option and sub-command. + */ + static const RTGETOPTDEF s_aOptions[] = + { + MEDIUMIOCOMMONOPT_DEFS(), + /* sub-commands */ + { "formatfat", 1000, RTGETOPT_REQ_NOTHING }, + { "cat", 1001, RTGETOPT_REQ_NOTHING }, + { "stream", 1002, RTGETOPT_REQ_NOTHING }, + }; + MEDIUMIOCOMMONOPT CommonOpts = { NULL, DeviceType_Null, NULL }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + RTGETOPTUNION ValueUnion; + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + MEDIUMIOCOMMONOPT_CASES(&CommonOpts); + + /* Sub-commands: */ + case 1000: + setCurrentSubcommand(HELP_SCOPE_MEDIUMIO_FORMATFAT); + return handleMediumIOFormatFat(a, GetState.iNext, &CommonOpts); + case 1001: + setCurrentSubcommand(HELP_SCOPE_MEDIUMIO_CAT); + return handleMediumIOCat(a, GetState.iNext, &CommonOpts); + case 1002: + setCurrentSubcommand(HELP_SCOPE_MEDIUMIO_STREAM); + return handleMediumIOStream(a, GetState.iNext, &CommonOpts); + + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + return errorNoSubcommand(); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp new file mode 100644 index 00000000..f5a1e446 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp @@ -0,0 +1,3707 @@ +/* $Id: VBoxManageGuestCtrl.cpp $ */ +/** @file + * VBoxManage - Implementation of guestcontrol command. + */ + +/* + * Copyright (C) 2010-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "VBoxManage.h" +#include "VBoxManageGuestCtrl.h" + +#include <VBox/com/array.h> +#include <VBox/com/com.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/listeners.h> +#include <VBox/com/NativeEventQueue.h> +#include <VBox/com/string.h> +#include <VBox/com/VirtualBox.h> + +#include <VBox/err.h> +#include <VBox/log.h> + +#include <iprt/asm.h> +#include <iprt/dir.h> +#include <iprt/file.h> +#include <iprt/getopt.h> +#include <iprt/list.h> +#include <iprt/path.h> +#include <iprt/process.h> /* For RTProcSelf(). */ +#include <iprt/semaphore.h> +#include <iprt/thread.h> +#include <iprt/vfs.h> + +#include <iprt/cpp/path.h> + +#include <map> +#include <vector> + +#ifdef USE_XPCOM_QUEUE +# include <sys/select.h> +# include <errno.h> +#endif + +#include <signal.h> + +#ifdef RT_OS_DARWIN +# include <CoreFoundation/CFRunLoop.h> +#endif + +using namespace com; + + +/********************************************************************************************************************************* + * Defined Constants And Macros * +*********************************************************************************************************************************/ + +#define GCTLCMD_COMMON_OPT_USER 999 /**< The --username option number. */ +#define GCTLCMD_COMMON_OPT_PASSWORD 998 /**< The --password option number. */ +#define GCTLCMD_COMMON_OPT_PASSWORD_FILE 997 /**< The --password-file option number. */ +#define GCTLCMD_COMMON_OPT_DOMAIN 996 /**< The --domain option number. */ +/** Common option definitions. */ +#define GCTLCMD_COMMON_OPTION_DEFS() \ + { "--user", GCTLCMD_COMMON_OPT_USER, RTGETOPT_REQ_STRING }, \ + { "--username", GCTLCMD_COMMON_OPT_USER, RTGETOPT_REQ_STRING }, \ + { "--passwordfile", GCTLCMD_COMMON_OPT_PASSWORD_FILE, RTGETOPT_REQ_STRING }, \ + { "--password", GCTLCMD_COMMON_OPT_PASSWORD, RTGETOPT_REQ_STRING }, \ + { "--domain", GCTLCMD_COMMON_OPT_DOMAIN, RTGETOPT_REQ_STRING }, \ + { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, \ + { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, + +/** Handles common options in the typical option parsing switch. */ +#define GCTLCMD_COMMON_OPTION_CASES(a_pCtx, a_ch, a_pValueUnion) \ + case 'v': \ + case 'q': \ + case GCTLCMD_COMMON_OPT_USER: \ + case GCTLCMD_COMMON_OPT_DOMAIN: \ + case GCTLCMD_COMMON_OPT_PASSWORD: \ + case GCTLCMD_COMMON_OPT_PASSWORD_FILE: \ + { \ + RTEXITCODE rcExitCommon = gctlCtxSetOption(a_pCtx, a_ch, a_pValueUnion); \ + if (RT_UNLIKELY(rcExitCommon != RTEXITCODE_SUCCESS)) \ + return rcExitCommon; \ + } break + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Set by the signal handler when current guest control + * action shall be aborted. */ +static volatile bool g_fGuestCtrlCanceled = false; +/** Event semaphore used for wait notifications. + * Also being used for the listener implementations in VBoxManageGuestCtrlListener.cpp. */ + RTSEMEVENT g_SemEventGuestCtrlCanceled = NIL_RTSEMEVENT; + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Listener declarations. + */ +VBOX_LISTENER_DECLARE(GuestFileEventListenerImpl) +VBOX_LISTENER_DECLARE(GuestProcessEventListenerImpl) +VBOX_LISTENER_DECLARE(GuestSessionEventListenerImpl) +VBOX_LISTENER_DECLARE(GuestEventListenerImpl) +VBOX_LISTENER_DECLARE(GuestAdditionsRunlevelListener) + +/** + * Definition of a guestcontrol command, with handler and various flags. + */ +typedef struct GCTLCMDDEF +{ + /** The command name. */ + const char *pszName; + + /** + * Actual command handler callback. + * + * @param pCtx Pointer to command context to use. + */ + DECLR3CALLBACKMEMBER(RTEXITCODE, pfnHandler, (struct GCTLCMDCTX *pCtx, int argc, char **argv)); + + /** The sub-command scope flags. */ + uint64_t fSubcommandScope; + /** Command context flags (GCTLCMDCTX_F_XXX). */ + uint32_t fCmdCtx; +} GCTLCMD; +/** Pointer to a const guest control command definition. */ +typedef GCTLCMDDEF const *PCGCTLCMDDEF; + +/** @name GCTLCMDCTX_F_XXX - Command context flags. + * @{ + */ +/** No flags set. */ +#define GCTLCMDCTX_F_NONE 0 +/** Don't install a signal handler (CTRL+C trap). */ +#define GCTLCMDCTX_F_NO_SIGNAL_HANDLER RT_BIT(0) +/** No guest session needed. */ +#define GCTLCMDCTX_F_SESSION_ANONYMOUS RT_BIT(1) +/** @} */ + +/** + * Context for handling a specific command. + */ +typedef struct GCTLCMDCTX +{ + HandlerArg *pArg; + + /** Pointer to the command definition. */ + PCGCTLCMDDEF pCmdDef; + /** The VM name or UUID. */ + const char *pszVmNameOrUuid; + + /** Whether we've done the post option parsing init already. */ + bool fPostOptionParsingInited; + /** Whether we've locked the VM session. */ + bool fLockedVmSession; + /** Whether to detach (@c true) or close the session. */ + bool fDetachGuestSession; + /** Set if we've installed the signal handler. */ + bool fInstalledSignalHandler; + /** The verbosity level. */ + uint32_t cVerbose; + /** User name. */ + Utf8Str strUsername; + /** Password. */ + Utf8Str strPassword; + /** Domain. */ + Utf8Str strDomain; + /** Pointer to the IGuest interface. */ + ComPtr<IGuest> pGuest; + /** Pointer to the to be used guest session. */ + ComPtr<IGuestSession> pGuestSession; + /** The guest session ID. */ + ULONG uSessionID; + +} GCTLCMDCTX, *PGCTLCMDCTX; + + +/** + * An entry for an element which needs to be copied/created to/on the guest. + */ +typedef struct DESTFILEENTRY +{ + DESTFILEENTRY(Utf8Str strFilename) : mFilename(strFilename) {} + Utf8Str mFilename; +} DESTFILEENTRY, *PDESTFILEENTRY; +/* + * Map for holding destination entries, whereas the key is the destination + * directory and the mapped value is a vector holding all elements for this directory. + */ +typedef std::map< Utf8Str, std::vector<DESTFILEENTRY> > DESTDIRMAP, *PDESTDIRMAP; +typedef std::map< Utf8Str, std::vector<DESTFILEENTRY> >::iterator DESTDIRMAPITER, *PDESTDIRMAPITER; + + +enum kStreamTransform +{ + kStreamTransform_None = 0, + kStreamTransform_Dos2Unix, + kStreamTransform_Unix2Dos +}; + + +DECLARE_TRANSLATION_CONTEXT(GuestCtrl); + + +#ifdef RT_OS_WINDOWS +static BOOL WINAPI gctlSignalHandler(DWORD dwCtrlType) RT_NOTHROW_DEF +{ + bool fEventHandled = FALSE; + switch (dwCtrlType) + { + /* User pressed CTRL+C or CTRL+BREAK or an external event was sent + * via GenerateConsoleCtrlEvent(). */ + case CTRL_BREAK_EVENT: + case CTRL_CLOSE_EVENT: + case CTRL_C_EVENT: + ASMAtomicWriteBool(&g_fGuestCtrlCanceled, true); + RTSemEventSignal(g_SemEventGuestCtrlCanceled); + fEventHandled = TRUE; + break; + default: + break; + /** @todo Add other events here. */ + } + + return fEventHandled; +} +#else /* !RT_OS_WINDOWS */ +/** + * Signal handler that sets g_fGuestCtrlCanceled. + * + * This can be executed on any thread in the process, on Windows it may even be + * a thread dedicated to delivering this signal. Don't do anything + * unnecessary here. + */ +static void gctlSignalHandler(int iSignal) RT_NOTHROW_DEF +{ + RT_NOREF(iSignal); + ASMAtomicWriteBool(&g_fGuestCtrlCanceled, true); + RTSemEventSignal(g_SemEventGuestCtrlCanceled); +} +#endif + + +/** + * Installs a custom signal handler to get notified + * whenever the user wants to intercept the program. + * + * @todo Make this handler available for all VBoxManage modules? + */ +static int gctlSignalHandlerInstall(void) +{ + g_fGuestCtrlCanceled = false; + + int vrc = VINF_SUCCESS; +#ifdef RT_OS_WINDOWS + if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)gctlSignalHandler, TRUE /* Add handler */)) + { + vrc = RTErrConvertFromWin32(GetLastError()); + RTMsgError(GuestCtrl::tr("Unable to install console control handler, vrc=%Rrc\n"), vrc); + } +#else + signal(SIGINT, gctlSignalHandler); + signal(SIGTERM, gctlSignalHandler); +# ifdef SIGBREAK + signal(SIGBREAK, gctlSignalHandler); +# endif +#endif + + if (RT_SUCCESS(vrc)) + vrc = RTSemEventCreate(&g_SemEventGuestCtrlCanceled); + + return vrc; +} + + +/** + * Uninstalls a previously installed signal handler. + */ +static int gctlSignalHandlerUninstall(void) +{ + int vrc = VINF_SUCCESS; +#ifdef RT_OS_WINDOWS + if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)NULL, FALSE /* Remove handler */)) + { + vrc = RTErrConvertFromWin32(GetLastError()); + RTMsgError(GuestCtrl::tr("Unable to uninstall console control handler, vrc=%Rrc\n"), vrc); + } +#else + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +# ifdef SIGBREAK + signal(SIGBREAK, SIG_DFL); +# endif +#endif + + if (g_SemEventGuestCtrlCanceled != NIL_RTSEMEVENT) + { + RTSemEventDestroy(g_SemEventGuestCtrlCanceled); + g_SemEventGuestCtrlCanceled = NIL_RTSEMEVENT; + } + return vrc; +} + + +/** + * Translates a process status to a human readable string. + * + * @sa GuestProcess::i_statusToString() + */ +const char *gctlProcessStatusToText(ProcessStatus_T enmStatus) +{ + switch (enmStatus) + { + case ProcessStatus_Starting: + return GuestCtrl::tr("starting"); + case ProcessStatus_Started: + return GuestCtrl::tr("started"); + case ProcessStatus_Paused: + return GuestCtrl::tr("paused"); + case ProcessStatus_Terminating: + return GuestCtrl::tr("terminating"); + case ProcessStatus_TerminatedNormally: + return GuestCtrl::tr("successfully terminated"); + case ProcessStatus_TerminatedSignal: + return GuestCtrl::tr("terminated by signal"); + case ProcessStatus_TerminatedAbnormally: + return GuestCtrl::tr("abnormally aborted"); + case ProcessStatus_TimedOutKilled: + return GuestCtrl::tr("timed out"); + case ProcessStatus_TimedOutAbnormally: + return GuestCtrl::tr("timed out, hanging"); + case ProcessStatus_Down: + return GuestCtrl::tr("killed"); + case ProcessStatus_Error: + return GuestCtrl::tr("error"); + default: + break; + } + return GuestCtrl::tr("unknown"); +} + +/** + * Translates a guest process wait result to a human readable string. + */ +static const char *gctlProcessWaitResultToText(ProcessWaitResult_T enmWaitResult) +{ + switch (enmWaitResult) + { + case ProcessWaitResult_Start: + return GuestCtrl::tr("started"); + case ProcessWaitResult_Terminate: + return GuestCtrl::tr("terminated"); + case ProcessWaitResult_Status: + return GuestCtrl::tr("status changed"); + case ProcessWaitResult_Error: + return GuestCtrl::tr("error"); + case ProcessWaitResult_Timeout: + return GuestCtrl::tr("timed out"); + case ProcessWaitResult_StdIn: + return GuestCtrl::tr("stdin ready"); + case ProcessWaitResult_StdOut: + return GuestCtrl::tr("data on stdout"); + case ProcessWaitResult_StdErr: + return GuestCtrl::tr("data on stderr"); + case ProcessWaitResult_WaitFlagNotSupported: + return GuestCtrl::tr("waiting flag not supported"); + default: + break; + } + return GuestCtrl::tr("unknown"); +} + +/** + * Translates a guest session status to a human readable string. + */ +const char *gctlGuestSessionStatusToText(GuestSessionStatus_T enmStatus) +{ + switch (enmStatus) + { + case GuestSessionStatus_Starting: + return GuestCtrl::tr("starting"); + case GuestSessionStatus_Started: + return GuestCtrl::tr("started"); + case GuestSessionStatus_Terminating: + return GuestCtrl::tr("terminating"); + case GuestSessionStatus_Terminated: + return GuestCtrl::tr("terminated"); + case GuestSessionStatus_TimedOutKilled: + return GuestCtrl::tr("timed out"); + case GuestSessionStatus_TimedOutAbnormally: + return GuestCtrl::tr("timed out, hanging"); + case GuestSessionStatus_Down: + return GuestCtrl::tr("killed"); + case GuestSessionStatus_Error: + return GuestCtrl::tr("error"); + default: + break; + } + return GuestCtrl::tr("unknown"); +} + +/** + * Translates a guest file status to a human readable string. + */ +const char *gctlFileStatusToText(FileStatus_T enmStatus) +{ + switch (enmStatus) + { + case FileStatus_Opening: + return GuestCtrl::tr("opening"); + case FileStatus_Open: + return GuestCtrl::tr("open"); + case FileStatus_Closing: + return GuestCtrl::tr("closing"); + case FileStatus_Closed: + return GuestCtrl::tr("closed"); + case FileStatus_Down: + return GuestCtrl::tr("killed"); + case FileStatus_Error: + return GuestCtrl::tr("error"); + default: + break; + } + return GuestCtrl::tr("unknown"); +} + +/** + * Translates a file system objec type to a string. + */ +const char *gctlFsObjTypeToName(FsObjType_T enmType) +{ + switch (enmType) + { + case FsObjType_Unknown: return GuestCtrl::tr("unknown"); + case FsObjType_Fifo: return GuestCtrl::tr("fifo"); + case FsObjType_DevChar: return GuestCtrl::tr("char-device"); + case FsObjType_Directory: return GuestCtrl::tr("directory"); + case FsObjType_DevBlock: return GuestCtrl::tr("block-device"); + case FsObjType_File: return GuestCtrl::tr("file"); + case FsObjType_Symlink: return GuestCtrl::tr("symlink"); + case FsObjType_Socket: return GuestCtrl::tr("socket"); + case FsObjType_WhiteOut: return GuestCtrl::tr("white-out"); +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case FsObjType_32BitHack: break; +#endif + } + return GuestCtrl::tr("unknown"); +} + +static int gctlPrintError(com::ErrorInfo &errorInfo) +{ + if ( errorInfo.isFullAvailable() + || errorInfo.isBasicAvailable()) + { + /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way + * because it contains more accurate info about what went wrong. */ + if (errorInfo.getResultCode() == VBOX_E_IPRT_ERROR) + RTMsgError("%ls.", errorInfo.getText().raw()); + else + { + RTMsgError(GuestCtrl::tr("Error details:")); + GluePrintErrorInfo(errorInfo); + } + return VERR_GENERAL_FAILURE; /** @todo */ + } + AssertMsgFailedReturn((GuestCtrl::tr("Object has indicated no error (%Rhrc)!?\n"), errorInfo.getResultCode()), + VERR_INVALID_PARAMETER); +} + +static int gctlPrintError(IUnknown *pObj, const GUID &aIID) +{ + com::ErrorInfo ErrInfo(pObj, aIID); + return gctlPrintError(ErrInfo); +} + +static int gctlPrintProgressError(ComPtr<IProgress> pProgress) +{ + int vrc = VINF_SUCCESS; + HRESULT hrc; + + do + { + BOOL fCanceled; + CHECK_ERROR_BREAK(pProgress, COMGETTER(Canceled)(&fCanceled)); + if (!fCanceled) + { + LONG rcProc; + CHECK_ERROR_BREAK(pProgress, COMGETTER(ResultCode)(&rcProc)); + if (FAILED(rcProc)) + { + com::ProgressErrorInfo ErrInfo(pProgress); + vrc = gctlPrintError(ErrInfo); + } + } + + } while(0); + + AssertMsgStmt(SUCCEEDED(hrc), (GuestCtrl::tr("Could not lookup progress information\n")), vrc = VERR_COM_UNEXPECTED); + + return vrc; +} + + + +/* + * + * + * Guest Control Command Context + * Guest Control Command Context + * Guest Control Command Context + * Guest Control Command Context + * + * + * + */ + + +/** + * Initializes a guest control command context structure. + * + * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE on failure (after + * informing the user of course). + * @param pCtx The command context to init. + * @param pArg The handle argument package. + */ +static RTEXITCODE gctrCmdCtxInit(PGCTLCMDCTX pCtx, HandlerArg *pArg) +{ + pCtx->pArg = pArg; + pCtx->pCmdDef = NULL; + pCtx->pszVmNameOrUuid = NULL; + pCtx->fPostOptionParsingInited = false; + pCtx->fLockedVmSession = false; + pCtx->fDetachGuestSession = false; + pCtx->fInstalledSignalHandler = false; + pCtx->cVerbose = 0; + pCtx->strUsername.setNull(); + pCtx->strPassword.setNull(); + pCtx->strDomain.setNull(); + pCtx->pGuest.setNull(); + pCtx->pGuestSession.setNull(); + pCtx->uSessionID = 0; + + /* + * The user name defaults to the host one, if we can get at it. + */ + char szUser[1024]; + int vrc = RTProcQueryUsername(RTProcSelf(), szUser, sizeof(szUser), NULL); + if ( RT_SUCCESS(vrc) + && RTStrIsValidEncoding(szUser)) /* paranoia was required on posix at some point, not needed any more! */ + { + try + { + pCtx->strUsername = szUser; + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Out of memory")); + } + } + /* else: ignore this failure. */ + + return RTEXITCODE_SUCCESS; +} + + +/** + * Worker for GCTLCMD_COMMON_OPTION_CASES. + * + * @returns RTEXITCODE_SUCCESS if the option was handled successfully. If not, + * an error message is printed and an appropriate failure exit code is + * returned. + * @param pCtx The guest control command context. + * @param ch The option char or ordinal. + * @param pValueUnion The option value union. + */ +static RTEXITCODE gctlCtxSetOption(PGCTLCMDCTX pCtx, int ch, PRTGETOPTUNION pValueUnion) +{ + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + switch (ch) + { + case GCTLCMD_COMMON_OPT_USER: /* User name */ + if (!pCtx->pCmdDef || !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)) + pCtx->strUsername = pValueUnion->psz; + else + RTMsgWarning(GuestCtrl::tr("The --username|-u option is ignored by '%s'"), pCtx->pCmdDef->pszName); + break; + + case GCTLCMD_COMMON_OPT_PASSWORD: /* Password */ + if (!pCtx->pCmdDef || !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)) + { + if (pCtx->strPassword.isNotEmpty()) + RTMsgWarning(GuestCtrl::tr("Password is given more than once.")); + pCtx->strPassword = pValueUnion->psz; + } + else + RTMsgWarning(GuestCtrl::tr("The --password option is ignored by '%s'"), pCtx->pCmdDef->pszName); + break; + + case GCTLCMD_COMMON_OPT_PASSWORD_FILE: /* Password file */ + if (!pCtx->pCmdDef || !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)) + rcExit = readPasswordFile(pValueUnion->psz, &pCtx->strPassword); + else + RTMsgWarning(GuestCtrl::tr("The --password-file|-p option is ignored by '%s'"), pCtx->pCmdDef->pszName); + break; + + case GCTLCMD_COMMON_OPT_DOMAIN: /* domain */ + if (!pCtx->pCmdDef || !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)) + pCtx->strDomain = pValueUnion->psz; + else + RTMsgWarning(GuestCtrl::tr("The --domain option is ignored by '%s'"), pCtx->pCmdDef->pszName); + break; + + case 'v': /* --verbose */ + pCtx->cVerbose++; + break; + + case 'q': /* --quiet */ + if (pCtx->cVerbose) + pCtx->cVerbose--; + break; + + default: + AssertFatalMsgFailed(("ch=%d (%c)\n", ch, ch)); + } + return rcExit; +} + + +/** + * Initializes the VM for IGuest operation. + * + * This opens a shared session to a running VM and gets hold of IGuest. + * + * @returns RTEXITCODE_SUCCESS on success. RTEXITCODE_FAILURE and user message + * on failure. + * @param pCtx The guest control command context. + * GCTLCMDCTX::pGuest will be set on success. + */ +static RTEXITCODE gctlCtxInitVmSession(PGCTLCMDCTX pCtx) +{ + HRESULT hrc; + AssertPtr(pCtx); + AssertPtr(pCtx->pArg); + + /* + * Find the VM and check if it's running. + */ + ComPtr<IMachine> machine; + CHECK_ERROR(pCtx->pArg->virtualBox, FindMachine(Bstr(pCtx->pszVmNameOrUuid).raw(), machine.asOutParam())); + if (SUCCEEDED(hrc)) + { + MachineState_T enmMachineState; + CHECK_ERROR(machine, COMGETTER(State)(&enmMachineState)); + if ( SUCCEEDED(hrc) + && enmMachineState == MachineState_Running) + { + /* + * It's running. So, open a session to it and get the IGuest interface. + */ + CHECK_ERROR(machine, LockMachine(pCtx->pArg->session, LockType_Shared)); + if (SUCCEEDED(hrc)) + { + pCtx->fLockedVmSession = true; + ComPtr<IConsole> ptrConsole; + CHECK_ERROR(pCtx->pArg->session, COMGETTER(Console)(ptrConsole.asOutParam())); + if (SUCCEEDED(hrc)) + { + if (ptrConsole.isNotNull()) + { + CHECK_ERROR(ptrConsole, COMGETTER(Guest)(pCtx->pGuest.asOutParam())); + if (SUCCEEDED(hrc)) + return RTEXITCODE_SUCCESS; + } + else + RTMsgError(GuestCtrl::tr("Failed to get a IConsole pointer for the machine. Is it still running?\n")); + } + } + } + else if (SUCCEEDED(hrc)) + RTMsgError(GuestCtrl::tr("Machine \"%s\" is not running (currently %s)!\n"), + pCtx->pszVmNameOrUuid, machineStateToName(enmMachineState, false)); + } + return RTEXITCODE_FAILURE; +} + + +/** + * Creates a guest session with the VM. + * + * @retval RTEXITCODE_SUCCESS on success. + * @retval RTEXITCODE_FAILURE and user message on failure. + * @param pCtx The guest control command context. + * GCTCMDCTX::pGuestSession and GCTLCMDCTX::uSessionID + * will be set. + */ +static RTEXITCODE gctlCtxInitGuestSession(PGCTLCMDCTX pCtx) +{ + HRESULT hrc; + AssertPtr(pCtx); + Assert(!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)); + Assert(pCtx->pGuest.isNotNull()); + + /* + * Build up a reasonable guest session name. Useful for identifying + * a specific session when listing / searching for them. + */ + char *pszSessionName; + if (RTStrAPrintf(&pszSessionName, + GuestCtrl::tr("[%RU32] VBoxManage Guest Control [%s] - %s"), + RTProcSelf(), pCtx->pszVmNameOrUuid, pCtx->pCmdDef->pszName) < 0) + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("No enough memory for session name")); + + /* + * Create a guest session. + */ + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Creating guest session as user '%s'...\n"), pCtx->strUsername.c_str()); + try + { + CHECK_ERROR(pCtx->pGuest, CreateSession(Bstr(pCtx->strUsername).raw(), + Bstr(pCtx->strPassword).raw(), + Bstr(pCtx->strDomain).raw(), + Bstr(pszSessionName).raw(), + pCtx->pGuestSession.asOutParam())); + } + catch (std::bad_alloc &) + { + RTMsgError(GuestCtrl::tr("Out of memory setting up IGuest::CreateSession call")); + hrc = E_OUTOFMEMORY; + } + if (SUCCEEDED(hrc)) + { + /* + * Wait for guest session to start. + */ + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Waiting for guest session to start...\n")); + GuestSessionWaitResult_T enmWaitResult = GuestSessionWaitResult_None; /* Shut up MSC */ + try + { + com::SafeArray<GuestSessionWaitForFlag_T> aSessionWaitFlags; + aSessionWaitFlags.push_back(GuestSessionWaitForFlag_Start); + CHECK_ERROR(pCtx->pGuestSession, WaitForArray(ComSafeArrayAsInParam(aSessionWaitFlags), + /** @todo Make session handling timeouts configurable. */ + 30 * 1000, &enmWaitResult)); + } + catch (std::bad_alloc &) + { + RTMsgError(GuestCtrl::tr("Out of memory setting up IGuestSession::WaitForArray call")); + hrc = E_OUTOFMEMORY; + } + if (SUCCEEDED(hrc)) + { + /* The WaitFlagNotSupported result may happen with GAs older than 4.3. */ + if ( enmWaitResult == GuestSessionWaitResult_Start + || enmWaitResult == GuestSessionWaitResult_WaitFlagNotSupported) + { + /* + * Get the session ID and we're ready to rumble. + */ + CHECK_ERROR(pCtx->pGuestSession, COMGETTER(Id)(&pCtx->uSessionID)); + if (SUCCEEDED(hrc)) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Successfully started guest session (ID %RU32)\n"), pCtx->uSessionID); + RTStrFree(pszSessionName); + return RTEXITCODE_SUCCESS; + } + } + else + { + GuestSessionStatus_T enmSessionStatus; + CHECK_ERROR(pCtx->pGuestSession, COMGETTER(Status)(&enmSessionStatus)); + RTMsgError(GuestCtrl::tr("Error starting guest session (current status is: %s)\n"), + SUCCEEDED(hrc) ? gctlGuestSessionStatusToText(enmSessionStatus) : GuestCtrl::tr("<unknown>")); + } + } + } + + RTStrFree(pszSessionName); + return RTEXITCODE_FAILURE; +} + + +/** + * Completes the guest control context initialization after parsing arguments. + * + * Will validate common arguments, open a VM session, and if requested open a + * guest session and install the CTRL-C signal handler. + * + * It is good to validate all the options and arguments you can before making + * this call. However, the VM session, IGuest and IGuestSession interfaces are + * not availabe till after this call, so take care. + * + * @retval RTEXITCODE_SUCCESS on success. + * @retval RTEXITCODE_FAILURE and user message on failure. + * @param pCtx The guest control command context. + * GCTCMDCTX::pGuestSession and GCTLCMDCTX::uSessionID + * will be set. + * @remarks Can safely be called multiple times, will only do work once. + */ +static RTEXITCODE gctlCtxPostOptionParsingInit(PGCTLCMDCTX pCtx) +{ + if (pCtx->fPostOptionParsingInited) + return RTEXITCODE_SUCCESS; + + /* + * Check that the user name isn't empty when we need it. + */ + RTEXITCODE rcExit; + if ( (pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS) + || pCtx->strUsername.isNotEmpty()) + { + /* + * Open the VM session and if required, a guest session. + */ + rcExit = gctlCtxInitVmSession(pCtx); + if ( rcExit == RTEXITCODE_SUCCESS + && !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS)) + rcExit = gctlCtxInitGuestSession(pCtx); + if (rcExit == RTEXITCODE_SUCCESS) + { + /* + * Install signal handler if requested (errors are ignored). + */ + if (!(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_NO_SIGNAL_HANDLER)) + { + int vrc = gctlSignalHandlerInstall(); + pCtx->fInstalledSignalHandler = RT_SUCCESS(vrc); + } + } + } + else + rcExit = errorSyntax(GuestCtrl::tr("No user name specified!")); + + pCtx->fPostOptionParsingInited = rcExit == RTEXITCODE_SUCCESS; + return rcExit; +} + + +/** + * Cleans up the context when the command returns. + * + * This will close any open guest session, unless the DETACH flag is set. + * It will also close any VM session that may be been established. Any signal + * handlers we've installed will also be removed. + * + * Un-initializes the VM after guest control usage. + * @param pCmdCtx Pointer to command context. + */ +static void gctlCtxTerm(PGCTLCMDCTX pCtx) +{ + HRESULT hrc; + AssertPtr(pCtx); + + /* + * Uninstall signal handler. + */ + if (pCtx->fInstalledSignalHandler) + { + gctlSignalHandlerUninstall(); + pCtx->fInstalledSignalHandler = false; + } + + /* + * Close, or at least release, the guest session. + */ + if (pCtx->pGuestSession.isNotNull()) + { + if ( !(pCtx->pCmdDef->fCmdCtx & GCTLCMDCTX_F_SESSION_ANONYMOUS) + && !pCtx->fDetachGuestSession) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Closing guest session ...\n")); + + CHECK_ERROR(pCtx->pGuestSession, Close()); + } + else if ( pCtx->fDetachGuestSession + && pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Guest session detached\n")); + + pCtx->pGuestSession.setNull(); + } + + /* + * Close the VM session. + */ + if (pCtx->fLockedVmSession) + { + Assert(pCtx->pArg->session.isNotNull()); + CHECK_ERROR(pCtx->pArg->session, UnlockMachine()); + pCtx->fLockedVmSession = false; + } +} + + + + + +/* + * + * + * Guest Control Command Handling. + * Guest Control Command Handling. + * Guest Control Command Handling. + * Guest Control Command Handling. + * Guest Control Command Handling. + * + * + */ + + +/** @name EXITCODEEXEC_XXX - Special run exit codes. + * + * Special exit codes for returning errors/information of a started guest + * process to the command line VBoxManage was started from. Useful for e.g. + * scripting. + * + * ASSUMING that all platforms have at least 7-bits for the exit code we can do + * the following mapping: + * - Guest exit code 0 is mapped to 0 on the host. + * - Guest exit codes 1 thru 93 (0x5d) are displaced by 32, so that 1 + * becomes 33 (0x21) on the host and 93 becomes 125 (0x7d) on the host. + * - Guest exit codes 94 (0x5e) and above are mapped to 126 (0x5e). + * + * We ASSUME that all VBoxManage status codes are in the range 0 thru 32. + * + * @note These are frozen as of 4.1.0. + * @note The guest exit code mappings was introduced with 5.0 and the 'run' + * command, they are/was not supported by 'exec'. + * @sa gctlRunCalculateExitCode + */ +/** Process exited normally but with an exit code <> 0. */ +#define EXITCODEEXEC_CODE ((RTEXITCODE)16) +#define EXITCODEEXEC_FAILED ((RTEXITCODE)17) +#define EXITCODEEXEC_TERM_SIGNAL ((RTEXITCODE)18) +#define EXITCODEEXEC_TERM_ABEND ((RTEXITCODE)19) +#define EXITCODEEXEC_TIMEOUT ((RTEXITCODE)20) +#define EXITCODEEXEC_DOWN ((RTEXITCODE)21) +/** Execution was interrupt by user (ctrl-c). */ +#define EXITCODEEXEC_CANCELED ((RTEXITCODE)22) +/** The first mapped guest (non-zero) exit code. */ +#define EXITCODEEXEC_MAPPED_FIRST 33 +/** The last mapped guest (non-zero) exit code value (inclusive). */ +#define EXITCODEEXEC_MAPPED_LAST 125 +/** The number of exit codes from EXITCODEEXEC_MAPPED_FIRST to + * EXITCODEEXEC_MAPPED_LAST. This is also the highest guest exit code number + * we're able to map. */ +#define EXITCODEEXEC_MAPPED_RANGE (93) +/** The guest exit code displacement value. */ +#define EXITCODEEXEC_MAPPED_DISPLACEMENT 32 +/** The guest exit code was too big to be mapped. */ +#define EXITCODEEXEC_MAPPED_BIG ((RTEXITCODE)126) +/** @} */ + +/** + * Calculates the exit code of VBoxManage. + * + * @returns The exit code to return. + * @param enmStatus The guest process status. + * @param uExitCode The associated guest process exit code (where + * applicable). + * @param fReturnExitCodes Set if we're to use the 32-126 range for guest + * exit codes. + */ +static RTEXITCODE gctlRunCalculateExitCode(ProcessStatus_T enmStatus, ULONG uExitCode, bool fReturnExitCodes) +{ + switch (enmStatus) + { + case ProcessStatus_TerminatedNormally: + if (uExitCode == 0) + return RTEXITCODE_SUCCESS; + if (!fReturnExitCodes) + return EXITCODEEXEC_CODE; + if (uExitCode <= EXITCODEEXEC_MAPPED_RANGE) + return (RTEXITCODE) (uExitCode + EXITCODEEXEC_MAPPED_DISPLACEMENT); + return EXITCODEEXEC_MAPPED_BIG; + + case ProcessStatus_TerminatedAbnormally: + return EXITCODEEXEC_TERM_ABEND; + case ProcessStatus_TerminatedSignal: + return EXITCODEEXEC_TERM_SIGNAL; + +#if 0 /* see caller! */ + case ProcessStatus_TimedOutKilled: + return EXITCODEEXEC_TIMEOUT; + case ProcessStatus_Down: + return EXITCODEEXEC_DOWN; /* Service/OS is stopping, process was killed. */ + case ProcessStatus_Error: + return EXITCODEEXEC_FAILED; + + /* The following is probably for detached? */ + case ProcessStatus_Starting: + return RTEXITCODE_SUCCESS; + case ProcessStatus_Started: + return RTEXITCODE_SUCCESS; + case ProcessStatus_Paused: + return RTEXITCODE_SUCCESS; + case ProcessStatus_Terminating: + return RTEXITCODE_SUCCESS; /** @todo ???? */ +#endif + + default: + AssertMsgFailed(("Unknown exit status (%u/%u) from guest process returned!\n", enmStatus, uExitCode)); + return RTEXITCODE_FAILURE; + } +} + + +/** + * Pumps guest output to the host. + * + * @return IPRT status code. + * @param pProcess Pointer to appropriate process object. + * @param hVfsIosDst Where to write the data. Can be the bit bucket or a (valid [std]) handle. + * @param uHandle Handle where to read the data from. + * @param cMsTimeout Timeout (in ms) to wait for the operation to + * complete. + */ +static int gctlRunPumpOutput(IProcess *pProcess, RTVFSIOSTREAM hVfsIosDst, ULONG uHandle, RTMSINTERVAL cMsTimeout) +{ + AssertPtrReturn(pProcess, VERR_INVALID_POINTER); + Assert(hVfsIosDst != NIL_RTVFSIOSTREAM); + + int vrc; + + SafeArray<BYTE> aOutputData; + HRESULT hrc = pProcess->Read(uHandle, _64K, RT_MAX(cMsTimeout, 1), ComSafeArrayAsOutParam(aOutputData)); + if (SUCCEEDED(hrc)) + { + size_t cbOutputData = aOutputData.size(); + if (cbOutputData == 0) + vrc = VINF_SUCCESS; + else + { + BYTE const *pbBuf = aOutputData.raw(); + AssertPtr(pbBuf); + + vrc = RTVfsIoStrmWrite(hVfsIosDst, pbBuf, cbOutputData, true /*fBlocking*/, NULL); + if (RT_FAILURE(vrc)) + RTMsgError(GuestCtrl::tr("Unable to write output, vrc=%Rrc\n"), vrc); + } + } + else + vrc = gctlPrintError(pProcess, COM_IIDOF(IProcess)); + return vrc; +} + + +/** + * Configures a host handle for pumping guest bits. + * + * @returns true if enabled and we successfully configured it. + * @param fEnabled Whether pumping this pipe is configured to std handles, + * or going to the bit bucket instead. + * @param enmHandle The IPRT standard handle designation. + * @param pszName The name for user messages. + * @param enmTransformation The transformation to apply. + * @param phVfsIos Where to return the resulting I/O stream handle. + */ +static bool gctlRunSetupHandle(bool fEnabled, RTHANDLESTD enmHandle, const char *pszName, + kStreamTransform enmTransformation, PRTVFSIOSTREAM phVfsIos) +{ + if (fEnabled) + { + int vrc = RTVfsIoStrmFromStdHandle(enmHandle, 0, true /*fLeaveOpen*/, phVfsIos); + if (RT_SUCCESS(vrc)) + { + if (enmTransformation != kStreamTransform_None) + { + RTMsgWarning(GuestCtrl::tr("Unsupported %s line ending conversion"), pszName); + /** @todo Implement dos2unix and unix2dos stream filters. */ + } + return true; + } + RTMsgWarning(GuestCtrl::tr("Error getting %s handle: %Rrc"), pszName, vrc); + } + else /* If disabled, all goes to / gets fed to/from the bit bucket. */ + { + RTFILE hFile; + int vrc = RTFileOpenBitBucket(&hFile, enmHandle == RTHANDLESTD_INPUT ? RTFILE_O_READ : RTFILE_O_WRITE); + if (RT_SUCCESS(vrc)) + { + vrc = RTVfsIoStrmFromRTFile(hFile, 0 /* fOpen */, false /* fLeaveOpen */, phVfsIos); + if (RT_SUCCESS(vrc)) + return true; + } + } + + return false; +} + + +/** + * Returns the remaining time (in ms) based on the start time and a set + * timeout value. Returns RT_INDEFINITE_WAIT if no timeout was specified. + * + * @return RTMSINTERVAL Time left (in ms). + * @param u64StartMs Start time (in ms). + * @param cMsTimeout Timeout value (in ms). + */ +static RTMSINTERVAL gctlRunGetRemainingTime(uint64_t u64StartMs, RTMSINTERVAL cMsTimeout) +{ + if (!cMsTimeout || cMsTimeout == RT_INDEFINITE_WAIT) /* If no timeout specified, wait forever. */ + return RT_INDEFINITE_WAIT; + + uint64_t u64ElapsedMs = RTTimeMilliTS() - u64StartMs; + if (u64ElapsedMs >= cMsTimeout) + return 0; + + return cMsTimeout - (RTMSINTERVAL)u64ElapsedMs; +} + +/** + * Common handler for the 'run' and 'start' commands. + * + * @returns Command exit code. + * @param pCtx Guest session context. + * @param argc The argument count. + * @param argv The argument vector for this command. + * @param fRunCmd Set if it's 'run' clear if 'start'. + */ +static RTEXITCODE gctlHandleRunCommon(PGCTLCMDCTX pCtx, int argc, char **argv, bool fRunCmd) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + /* + * Parse arguments. + */ + enum kGstCtrlRunOpt + { + kGstCtrlRunOpt_IgnoreOrphanedProcesses = 1000, + kGstCtrlRunOpt_NoProfile, /** @todo Deprecated and will be removed soon; use kGstCtrlRunOpt_Profile instead, if needed. */ + kGstCtrlRunOpt_Profile, + kGstCtrlRunOpt_Dos2Unix, + kGstCtrlRunOpt_Unix2Dos, + kGstCtrlRunOpt_WaitForStdOut, + kGstCtrlRunOpt_NoWaitForStdOut, + kGstCtrlRunOpt_WaitForStdErr, + kGstCtrlRunOpt_NoWaitForStdErr + }; + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--arg0", '0', RTGETOPT_REQ_STRING }, + { "--putenv", 'E', RTGETOPT_REQ_STRING }, + { "--exe", 'e', RTGETOPT_REQ_STRING }, + { "--timeout", 't', RTGETOPT_REQ_UINT32 }, + { "--unquoted-args", 'u', RTGETOPT_REQ_NOTHING }, + { "--ignore-orphaned-processes", kGstCtrlRunOpt_IgnoreOrphanedProcesses, RTGETOPT_REQ_NOTHING }, + { "--no-profile", kGstCtrlRunOpt_NoProfile, RTGETOPT_REQ_NOTHING }, /** @todo Deprecated. */ + { "--profile", kGstCtrlRunOpt_Profile, RTGETOPT_REQ_NOTHING }, + /* run only: 6 - options */ + { "--dos2unix", kGstCtrlRunOpt_Dos2Unix, RTGETOPT_REQ_NOTHING }, + { "--unix2dos", kGstCtrlRunOpt_Unix2Dos, RTGETOPT_REQ_NOTHING }, + { "--no-wait-stdout", kGstCtrlRunOpt_NoWaitForStdOut, RTGETOPT_REQ_NOTHING }, + { "--wait-stdout", kGstCtrlRunOpt_WaitForStdOut, RTGETOPT_REQ_NOTHING }, + { "--no-wait-stderr", kGstCtrlRunOpt_NoWaitForStdErr, RTGETOPT_REQ_NOTHING }, + { "--wait-stderr", kGstCtrlRunOpt_WaitForStdErr, RTGETOPT_REQ_NOTHING }, + }; + + /** @todo stdin handling. */ + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions) - (fRunCmd ? 0 : 6), + 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRC(vrc); + + com::SafeArray<ProcessCreateFlag_T> aCreateFlags; + com::SafeArray<ProcessWaitForFlag_T> aWaitFlags; + com::SafeArray<IN_BSTR> aArgs; + com::SafeArray<IN_BSTR> aEnv; + const char * pszImage = NULL; + const char * pszArg0 = NULL; /* Argument 0 to use. pszImage will be used if not specified. */ + bool fWaitForStdOut = fRunCmd; + bool fWaitForStdErr = fRunCmd; + RTVFSIOSTREAM hVfsStdOut = NIL_RTVFSIOSTREAM; + RTVFSIOSTREAM hVfsStdErr = NIL_RTVFSIOSTREAM; + enum kStreamTransform enmStdOutTransform = kStreamTransform_None; + enum kStreamTransform enmStdErrTransform = kStreamTransform_None; + RTMSINTERVAL cMsTimeout = 0; + + try + { + /* Wait for process start in any case. This is useful for scripting VBoxManage + * when relying on its overall exit code. */ + aWaitFlags.push_back(ProcessWaitForFlag_Start); + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'E': + if ( ValueUnion.psz[0] == '\0' + || ValueUnion.psz[0] == '=') + return errorSyntax(GuestCtrl::tr("Invalid argument variable[=value]: '%s'"), ValueUnion.psz); + aEnv.push_back(Bstr(ValueUnion.psz).raw()); + break; + + case kGstCtrlRunOpt_IgnoreOrphanedProcesses: + aCreateFlags.push_back(ProcessCreateFlag_IgnoreOrphanedProcesses); + break; + + case kGstCtrlRunOpt_NoProfile: + /** @todo Deprecated, will be removed. */ + RTPrintf(GuestCtrl::tr("Warning: Deprecated option \"--no-profile\" specified\n")); + break; + + case kGstCtrlRunOpt_Profile: + aCreateFlags.push_back(ProcessCreateFlag_Profile); + break; + + case '0': + pszArg0 = ValueUnion.psz; + break; + + case 'e': + pszImage = ValueUnion.psz; + break; + + case 'u': + aCreateFlags.push_back(ProcessCreateFlag_UnquotedArguments); + break; + + /** @todo Add a hidden flag. */ + + case 't': /* Timeout */ + cMsTimeout = ValueUnion.u32; + break; + + /* run only options: */ + case kGstCtrlRunOpt_Dos2Unix: + Assert(fRunCmd); + enmStdErrTransform = enmStdOutTransform = kStreamTransform_Dos2Unix; + break; + case kGstCtrlRunOpt_Unix2Dos: + Assert(fRunCmd); + enmStdErrTransform = enmStdOutTransform = kStreamTransform_Unix2Dos; + break; + + case kGstCtrlRunOpt_WaitForStdOut: + Assert(fRunCmd); + fWaitForStdOut = true; + break; + case kGstCtrlRunOpt_NoWaitForStdOut: + Assert(fRunCmd); + fWaitForStdOut = false; + break; + + case kGstCtrlRunOpt_WaitForStdErr: + Assert(fRunCmd); + fWaitForStdErr = true; + break; + case kGstCtrlRunOpt_NoWaitForStdErr: + Assert(fRunCmd); + fWaitForStdErr = false; + break; + + case VINF_GETOPT_NOT_OPTION: + /* VINF_GETOPT_NOT_OPTION comes after all options have been specified; + * so if pszImage still is zero at this stage, we use the first non-option found + * as the image being executed. */ + if (!pszImage) + pszImage = ValueUnion.psz; + else /* Add anything else to the arguments vector. */ + aArgs.push_back(Bstr(ValueUnion.psz).raw()); + break; + + default: + return errorGetOpt(ch, &ValueUnion); + + } /* switch */ + } /* while RTGetOpt */ + + /* Must have something to execute. */ + if (!pszImage || !*pszImage) + return errorSyntax(GuestCtrl::tr("No executable specified!")); + + /* Set the arg0 argument (descending precedence): + * - If an argument 0 is explicitly specified (via "--arg0"), use this as argument 0. + * - When an image is specified explicitly (via "--exe <image>"), use <image> as argument 0. + * Note: This is (and ever was) the default behavior users expect, so don't change this! */ + if (pszArg0) + aArgs.push_front(Bstr(pszArg0).raw()); + else + aArgs.push_front(Bstr(pszImage).raw()); + + if (pCtx->cVerbose) /* Print the final execution parameters in verbose mode. */ + { + RTPrintf(GuestCtrl::tr("Executing:\n Image : %s\n"), pszImage); + for (size_t i = 0; i < aArgs.size(); i++) + RTPrintf(GuestCtrl::tr(" arg[%d]: %ls\n"), i, aArgs[i]); + } + /* No altering of aArgs and/or pszImage after this point! */ + + /* + * Finalize process creation and wait flags and input/output streams. + */ + if (!fRunCmd) + { + aCreateFlags.push_back(ProcessCreateFlag_WaitForProcessStartOnly); + Assert(!fWaitForStdOut); + Assert(!fWaitForStdErr); + } + else + { + aWaitFlags.push_back(ProcessWaitForFlag_Terminate); + fWaitForStdOut = gctlRunSetupHandle(fWaitForStdOut, RTHANDLESTD_OUTPUT, "stdout", enmStdOutTransform, &hVfsStdOut); + if (fWaitForStdOut) + { + aCreateFlags.push_back(ProcessCreateFlag_WaitForStdOut); + aWaitFlags.push_back(ProcessWaitForFlag_StdOut); + } + fWaitForStdErr = gctlRunSetupHandle(fWaitForStdErr, RTHANDLESTD_ERROR, "stderr", enmStdErrTransform, &hVfsStdErr); + if (fWaitForStdErr) + { + aCreateFlags.push_back(ProcessCreateFlag_WaitForStdErr); + aWaitFlags.push_back(ProcessWaitForFlag_StdErr); + } + } + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, "VERR_NO_MEMORY\n"); + } + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + HRESULT hrc; + + try + { + do + { + /* Get current time stamp to later calculate rest of timeout left. */ + uint64_t msStart = RTTimeMilliTS(); + + /* + * Create the process. + */ + if (pCtx->cVerbose) + { + if (cMsTimeout == 0) + RTPrintf(GuestCtrl::tr("Starting guest process ...\n")); + else + RTPrintf(GuestCtrl::tr("Starting guest process (within %ums)\n"), cMsTimeout); + } + ComPtr<IGuestProcess> pProcess; + CHECK_ERROR_BREAK(pCtx->pGuestSession, ProcessCreate(Bstr(pszImage).raw(), + ComSafeArrayAsInParam(aArgs), + ComSafeArrayAsInParam(aEnv), + ComSafeArrayAsInParam(aCreateFlags), + gctlRunGetRemainingTime(msStart, cMsTimeout), + pProcess.asOutParam())); + + /* + * Explicitly wait for the guest process to be in a started state. + */ + com::SafeArray<ProcessWaitForFlag_T> aWaitStartFlags; + aWaitStartFlags.push_back(ProcessWaitForFlag_Start); + ProcessWaitResult_T waitResult; + CHECK_ERROR_BREAK(pProcess, WaitForArray(ComSafeArrayAsInParam(aWaitStartFlags), + gctlRunGetRemainingTime(msStart, cMsTimeout), &waitResult)); + + ULONG uPID = 0; + CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID)); + if (fRunCmd && pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process '%s' (PID %RU32) started\n"), pszImage, uPID); + else if (!fRunCmd && pCtx->cVerbose) + { + /* Just print plain PID to make it easier for scripts + * invoking VBoxManage. */ + RTPrintf(GuestCtrl::tr("[%RU32 - Session %RU32]\n"), uPID, pCtx->uSessionID); + } + + /* + * Wait for process to exit/start... + */ + RTMSINTERVAL cMsTimeLeft = 1; /* Will be calculated. */ + bool fReadStdOut = false; + bool fReadStdErr = false; + bool fCompleted = false; + bool fCompletedStartCmd = false; + + vrc = VINF_SUCCESS; + while ( !fCompleted + && cMsTimeLeft > 0) + { + cMsTimeLeft = gctlRunGetRemainingTime(msStart, cMsTimeout); + CHECK_ERROR_BREAK(pProcess, WaitForArray(ComSafeArrayAsInParam(aWaitFlags), + RT_MIN(500 /*ms*/, RT_MAX(cMsTimeLeft, 1 /*ms*/)), + &waitResult)); + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Wait result is '%s' (%d)\n"), gctlProcessWaitResultToText(waitResult), waitResult); + switch (waitResult) + { + case ProcessWaitResult_Start: /** @todo you always wait for 'start', */ + fCompletedStartCmd = fCompleted = !fRunCmd; /* Only wait for startup if the 'start' command. */ + if (!fCompleted && aWaitFlags[0] == ProcessWaitForFlag_Start) + aWaitFlags[0] = ProcessWaitForFlag_Terminate; + break; + case ProcessWaitResult_StdOut: + fReadStdOut = true; + break; + case ProcessWaitResult_StdErr: + fReadStdErr = true; + break; + case ProcessWaitResult_Terminate: + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process terminated\n")); + /* Process terminated, we're done. */ + fCompleted = true; + break; + case ProcessWaitResult_WaitFlagNotSupported: + /* The guest does not support waiting for stdout/err, so + * yield to reduce the CPU load due to busy waiting. */ + RTThreadYield(); + fReadStdOut = fReadStdErr = true; + /* Note: In case the user specified explicitly not wanting to wait for stdout / stderr, + * the configured VFS handle goes to / will be fed from the bit bucket. */ + break; + case ProcessWaitResult_Timeout: + { + /** @todo It is really unclear whether we will get stuck with the timeout + * result here if the guest side times out the process and fails to + * kill the process... To be on the save side, double the IPC and + * check the process status every time we time out. */ + ProcessStatus_T enmProcStatus; + CHECK_ERROR_BREAK(pProcess, COMGETTER(Status)(&enmProcStatus)); + if ( enmProcStatus == ProcessStatus_TimedOutKilled + || enmProcStatus == ProcessStatus_TimedOutAbnormally) + fCompleted = true; + fReadStdOut = fReadStdErr = true; + break; + } + case ProcessWaitResult_Status: + /* ignore. */ + break; + case ProcessWaitResult_Error: + /* waitFor is dead in the water, I think, so better leave the loop. */ + vrc = VERR_CALLBACK_RETURN; + break; + + case ProcessWaitResult_StdIn: AssertFailed(); /* did ask for this! */ break; + case ProcessWaitResult_None: AssertFailed(); /* used. */ break; + default: AssertFailed(); /* huh? */ break; + } + + if (g_fGuestCtrlCanceled) + break; + + /* + * Pump output as needed. + */ + if (fReadStdOut) + { + cMsTimeLeft = gctlRunGetRemainingTime(msStart, cMsTimeout); + int vrc2 = gctlRunPumpOutput(pProcess, hVfsStdOut, 1 /* StdOut */, cMsTimeLeft); + if (RT_FAILURE(vrc2) && RT_SUCCESS(vrc)) + vrc = vrc2; + fReadStdOut = false; + } + if (fReadStdErr) + { + cMsTimeLeft = gctlRunGetRemainingTime(msStart, cMsTimeout); + int vrc2 = gctlRunPumpOutput(pProcess, hVfsStdErr, 2 /* StdErr */, cMsTimeLeft); + if (RT_FAILURE(vrc2) && RT_SUCCESS(vrc)) + vrc = vrc2; + fReadStdErr = false; + } + if ( RT_FAILURE(vrc) + || g_fGuestCtrlCanceled) + break; + + /* + * Process events before looping. + */ + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + } /* while */ + + /* + * Report status back to the user. + */ + if (g_fGuestCtrlCanceled) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process execution aborted!\n")); + rcExit = EXITCODEEXEC_CANCELED; + } + else if (fCompletedStartCmd) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process successfully started!\n")); + rcExit = RTEXITCODE_SUCCESS; + } + else if (fCompleted) + { + ProcessStatus_T procStatus; + CHECK_ERROR_BREAK(pProcess, COMGETTER(Status)(&procStatus)); + if ( procStatus == ProcessStatus_TerminatedNormally + || procStatus == ProcessStatus_TerminatedAbnormally + || procStatus == ProcessStatus_TerminatedSignal) + { + LONG lExitCode; + CHECK_ERROR_BREAK(pProcess, COMGETTER(ExitCode)(&lExitCode)); + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Exit code=%u (Status=%u [%s])\n"), + lExitCode, procStatus, gctlProcessStatusToText(procStatus)); + + rcExit = gctlRunCalculateExitCode(procStatus, lExitCode, true /*fReturnExitCodes*/); + } + else if ( procStatus == ProcessStatus_TimedOutKilled + || procStatus == ProcessStatus_TimedOutAbnormally) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process timed out (guest side) and %s\n"), + procStatus == ProcessStatus_TimedOutAbnormally + ? GuestCtrl::tr("failed to terminate so far") : GuestCtrl::tr("was terminated")); + rcExit = EXITCODEEXEC_TIMEOUT; + } + else + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process now is in status [%s] (unexpected)\n"), + gctlProcessStatusToText(procStatus)); + rcExit = RTEXITCODE_FAILURE; + } + } + else if (RT_FAILURE_NP(vrc)) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process monitor loop quit with vrc=%Rrc\n"), vrc); + rcExit = RTEXITCODE_FAILURE; + } + else + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Process monitor loop timed out\n")); + rcExit = EXITCODEEXEC_TIMEOUT; + } + + } while (0); + } + catch (std::bad_alloc &) + { + hrc = E_OUTOFMEMORY; + } + + /* + * Decide what to do with the guest session. + * + * If it's the 'start' command where detach the guest process after + * starting, don't close the guest session it is part of, except on + * failure or ctrl-c. + * + * For the 'run' command the guest process quits with us. + */ + if (!fRunCmd && SUCCEEDED(hrc) && !g_fGuestCtrlCanceled) + pCtx->fDetachGuestSession = true; + + /* Make sure we return failure on failure. */ + if (FAILED(hrc) && rcExit == RTEXITCODE_SUCCESS) + rcExit = RTEXITCODE_FAILURE; + return rcExit; +} + + +static DECLCALLBACK(RTEXITCODE) gctlHandleRun(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + return gctlHandleRunCommon(pCtx, argc, argv, true /*fRunCmd*/); +} + + +static DECLCALLBACK(RTEXITCODE) gctlHandleStart(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + return gctlHandleRunCommon(pCtx, argc, argv, false /*fRunCmd*/); +} + + +static RTEXITCODE gctlHandleCopy(PGCTLCMDCTX pCtx, int argc, char **argv, bool fHostToGuest) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + /* + * IGuest::CopyToGuest is kept as simple as possible to let the developer choose + * what and how to implement the file enumeration/recursive lookup, like VBoxManage + * does in here. + */ + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--follow", 'L', RTGETOPT_REQ_NOTHING }, /* Kept for backwards-compatibility (VBox < 7.0). */ + { "--dereference", 'L', RTGETOPT_REQ_NOTHING }, + { "--no-replace", 'n', RTGETOPT_REQ_NOTHING }, /* like "-n" via cp. */ + { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, + { "--target-directory", 't', RTGETOPT_REQ_STRING }, + { "--update", 'u', RTGETOPT_REQ_NOTHING } /* like "-u" via cp. */ + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + bool fDstMustBeDir = false; + const char *pszDst = NULL; + bool fFollow = false; + bool fRecursive = false; + bool fUpdate = false; /* Whether to copy the file only if it's newer than the target. */ + bool fNoReplace = false; /* Only copy the file if it does not exist yet. */ + + int vrc = VINF_SUCCESS; + while ( (ch = RTGetOpt(&GetState, &ValueUnion)) != 0 + && ch != VINF_GETOPT_NOT_OPTION) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'L': + if (!RTStrICmp(ValueUnion.pDef->pszLong, "--follow")) + RTMsgWarning("--follow is deprecated; use --dereference instead."); + fFollow = true; + break; + + case 'n': + fNoReplace = true; + break; + + case 'R': + fRecursive = true; + break; + + case 't': + pszDst = ValueUnion.psz; + fDstMustBeDir = true; + break; + + case 'u': + fUpdate = true; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + char **papszSources = RTGetOptNonOptionArrayPtr(&GetState); + size_t cSources = &argv[argc] - papszSources; + + if (!cSources) + return errorSyntax(GuestCtrl::tr("No sources specified!")); + + /* Unless a --target-directory is given, the last argument is the destination, so + bump it from the source list. */ + if (pszDst == NULL && cSources >= 2) + pszDst = papszSources[--cSources]; + + if (pszDst == NULL) + return errorSyntax(GuestCtrl::tr("No destination specified!")); + + char szAbsDst[RTPATH_MAX]; + if (!fHostToGuest) + { + vrc = RTPathAbs(pszDst, szAbsDst, sizeof(szAbsDst)); + if (RT_SUCCESS(vrc)) + pszDst = szAbsDst; + else + return RTMsgErrorExitFailure(GuestCtrl::tr("RTPathAbs failed on '%s': %Rrc"), pszDst, vrc); + } + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + /* + * Done parsing arguments, do some more preparations. + */ + if (pCtx->cVerbose) + { + if (fHostToGuest) + RTPrintf(GuestCtrl::tr("Copying from host to guest ...\n")); + else + RTPrintf(GuestCtrl::tr("Copying from guest to host ...\n")); + } + + HRESULT hrc = S_OK; + + com::SafeArray<IN_BSTR> aSources; + com::SafeArray<IN_BSTR> aFilters; /** @todo Populate those? For now we use caller-based globbing. */ + com::SafeArray<IN_BSTR> aCopyFlags; + + size_t iSrc = 0; + for (; iSrc < cSources; iSrc++) + { + aSources.push_back(Bstr(papszSources[iSrc]).raw()); + aFilters.push_back(Bstr("").raw()); /* Empty for now. See @todo above. */ + + /* Compile the comma-separated list of flags. + * Certain flags are only available for specific file system objects, e.g. directories. */ + bool fIsDir = false; + if (fHostToGuest) + { + RTFSOBJINFO ObjInfo; + vrc = RTPathQueryInfo(papszSources[iSrc], &ObjInfo, RTFSOBJATTRADD_NOTHING); + if (RT_SUCCESS(vrc)) + fIsDir = RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode); + + if (RT_FAILURE(vrc)) + break; + } + else /* Guest to host. */ + { + ComPtr<IGuestFsObjInfo> pFsObjInfo; + hrc = pCtx->pGuestSession->FsObjQueryInfo(Bstr(papszSources[iSrc]).raw(), RT_BOOL(fFollow) /* fFollowSymlinks */, + pFsObjInfo.asOutParam()); + if (SUCCEEDED(hrc)) + { + FsObjType_T enmObjType; + CHECK_ERROR(pFsObjInfo,COMGETTER(Type)(&enmObjType)); + if (SUCCEEDED(hrc)) + { + /* Take action according to source file. */ + fIsDir = enmObjType == FsObjType_Directory; + } + } + + if (FAILED(hrc)) + { + vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); + break; + } + } + + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Source '%s' is a %s\n"), papszSources[iSrc], fIsDir ? "directory" : "file"); + + Utf8Str strCopyFlags; + if (fRecursive && fIsDir) /* Only available for directories. Just ignore otherwise. */ + strCopyFlags += "Recursive,"; + if (fFollow) + strCopyFlags += "FollowLinks,"; + if (fUpdate) /* Only copy source files which are newer than the destination file. */ + strCopyFlags += "Update,"; + if (fNoReplace) /* Do not overwrite files. */ + strCopyFlags += "NoReplace,"; + else if (!fNoReplace && fIsDir) + strCopyFlags += "CopyIntoExisting,"; /* Only copy into existing directories if "--no-replace" isn't specified. */ + aCopyFlags.push_back(Bstr(strCopyFlags).raw()); + } + + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(GuestCtrl::tr("Error looking file system information for source '%s', vrc=%Rrc"), + papszSources[iSrc], vrc); + + ComPtr<IProgress> pProgress; + if (fHostToGuest) + { + hrc = pCtx->pGuestSession->CopyToGuest(ComSafeArrayAsInParam(aSources), + ComSafeArrayAsInParam(aFilters), ComSafeArrayAsInParam(aCopyFlags), + Bstr(pszDst).raw(), pProgress.asOutParam()); + } + else /* Guest to host. */ + { + hrc = pCtx->pGuestSession->CopyFromGuest(ComSafeArrayAsInParam(aSources), + ComSafeArrayAsInParam(aFilters), ComSafeArrayAsInParam(aCopyFlags), + Bstr(pszDst).raw(), pProgress.asOutParam()); + } + + if (FAILED(hrc)) + { + vrc = gctlPrintError(pCtx->pGuestSession, COM_IIDOF(IGuestSession)); + } + else if (pProgress.isNotNull()) + { + if (pCtx->cVerbose) + hrc = showProgress(pProgress); + else + hrc = pProgress->WaitForCompletion(-1 /* No timeout */); + if (SUCCEEDED(hrc)) + CHECK_PROGRESS_ERROR(pProgress, (GuestCtrl::tr("File copy failed"))); + vrc = gctlPrintProgressError(pProgress); + } + + if (RT_FAILURE(vrc)) + rcExit = RTEXITCODE_FAILURE; + + return rcExit; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleCopyFrom(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + return gctlHandleCopy(pCtx, argc, argv, false /* Guest to host */); +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleCopyTo(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + return gctlHandleCopy(pCtx, argc, argv, true /* Host to guest */); +} + +static DECLCALLBACK(RTEXITCODE) gctrlHandleMkDir(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--mode", 'm', RTGETOPT_REQ_UINT32 }, + { "--parents", 'P', RTGETOPT_REQ_NOTHING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + SafeArray<DirectoryCreateFlag_T> aDirCreateFlags; + uint32_t fDirMode = 0; /* Default mode. */ + uint32_t cDirsCreated = 0; + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'm': /* Mode */ + fDirMode = ValueUnion.u32; + break; + + case 'P': /* Create parents */ + aDirCreateFlags.push_back(DirectoryCreateFlag_Parents); + break; + + case VINF_GETOPT_NOT_OPTION: + if (cDirsCreated == 0) + { + /* + * First non-option - no more options now. + */ + rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Creating %RU32 directories...\n", "", argc - GetState.iNext + 1), + argc - GetState.iNext + 1); + } + if (g_fGuestCtrlCanceled) + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("mkdir was interrupted by Ctrl-C (%u left)\n"), + argc - GetState.iNext + 1); + + /* + * Create the specified directory. + * + * On failure we'll change the exit status to failure and + * continue with the next directory that needs creating. We do + * this because we only create new things, and because this is + * how /bin/mkdir works on unix. + */ + cDirsCreated++; + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Creating directory \"%s\" ...\n"), ValueUnion.psz); + try + { + HRESULT hrc; + CHECK_ERROR(pCtx->pGuestSession, DirectoryCreate(Bstr(ValueUnion.psz).raw(), + fDirMode, ComSafeArrayAsInParam(aDirCreateFlags))); + if (FAILED(hrc)) + rcExit = RTEXITCODE_FAILURE; + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Out of memory\n")); + } + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (!cDirsCreated) + return errorSyntax(GuestCtrl::tr("No directory to create specified!")); + return rcExit; +} + + +static DECLCALLBACK(RTEXITCODE) gctlHandleRmDir(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--recursive", 'R', RTGETOPT_REQ_NOTHING }, + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + bool fRecursive = false; + uint32_t cDirRemoved = 0; + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'R': + fRecursive = true; + break; + + case VINF_GETOPT_NOT_OPTION: + { + if (cDirRemoved == 0) + { + /* + * First non-option - no more options now. + */ + rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + if (pCtx->cVerbose) + { + if (fRecursive) + RTPrintf(GuestCtrl::tr("Removing %RU32 directory tree(s)...\n", "", argc - GetState.iNext + 1), + argc - GetState.iNext + 1); + else + RTPrintf(GuestCtrl::tr("Removing %RU32 directorie(s)...\n", "", argc - GetState.iNext + 1), + argc - GetState.iNext + 1); + } + } + if (g_fGuestCtrlCanceled) + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("rmdir was interrupted by Ctrl-C (%u left)\n"), + argc - GetState.iNext + 1); + + cDirRemoved++; + HRESULT hrc; + if (!fRecursive) + { + /* + * Remove exactly one directory. + */ + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Removing directory \"%s\" ...\n"), ValueUnion.psz); + try + { + CHECK_ERROR(pCtx->pGuestSession, DirectoryRemove(Bstr(ValueUnion.psz).raw())); + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Out of memory\n")); + } + } + else + { + /* + * Remove the directory and anything under it, that means files + * and everything. This is in the tradition of the Windows NT + * CMD.EXE "rmdir /s" operation, a tradition which jpsoft's TCC + * strongly warns against (and half-ways questions the sense of). + */ + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Recursively removing directory \"%s\" ...\n"), ValueUnion.psz); + try + { + /** @todo Make flags configurable. */ + com::SafeArray<DirectoryRemoveRecFlag_T> aRemRecFlags; + aRemRecFlags.push_back(DirectoryRemoveRecFlag_ContentAndDir); + + ComPtr<IProgress> ptrProgress; + CHECK_ERROR(pCtx->pGuestSession, DirectoryRemoveRecursive(Bstr(ValueUnion.psz).raw(), + ComSafeArrayAsInParam(aRemRecFlags), + ptrProgress.asOutParam())); + if (SUCCEEDED(hrc)) + { + if (pCtx->cVerbose) + hrc = showProgress(ptrProgress); + else + hrc = ptrProgress->WaitForCompletion(-1 /* indefinitely */); + if (SUCCEEDED(hrc)) + CHECK_PROGRESS_ERROR(ptrProgress, (GuestCtrl::tr("Directory deletion failed"))); + ptrProgress.setNull(); + } + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Out of memory during recursive rmdir\n")); + } + } + + /* + * This command returns immediately on failure since it's destructive in nature. + */ + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + break; + } + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (!cDirRemoved) + return errorSyntax(GuestCtrl::tr("No directory to remove specified!")); + return rcExit; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleRm(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--force", 'f', RTGETOPT_REQ_NOTHING, }, + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + uint32_t cFilesDeleted = 0; + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + bool fForce = true; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case VINF_GETOPT_NOT_OPTION: + if (cFilesDeleted == 0) + { + /* + * First non-option - no more options now. + */ + rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Removing %RU32 file(s)...\n", "", argc - GetState.iNext + 1), + argc - GetState.iNext + 1); + } + if (g_fGuestCtrlCanceled) + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("rm was interrupted by Ctrl-C (%u left)\n"), + argc - GetState.iNext + 1); + + /* + * Remove the specified file. + * + * On failure we will by default stop, however, the force option will + * by unix traditions force us to ignore errors and continue. + */ + cFilesDeleted++; + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Removing file \"%s\" ...\n", ValueUnion.psz)); + try + { + /** @todo How does IGuestSession::FsObjRemove work with read-only files? Do we + * need to do some chmod or whatever to better emulate the --force flag? */ + HRESULT hrc; + CHECK_ERROR(pCtx->pGuestSession, FsObjRemove(Bstr(ValueUnion.psz).raw())); + if (FAILED(hrc) && !fForce) + return RTEXITCODE_FAILURE; + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Out of memory\n")); + } + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (!cFilesDeleted && !fForce) + return errorSyntax(GuestCtrl::tr("No file to remove specified!")); + return rcExit; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleMv(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() +/** @todo Missing --force/-f flag. */ + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + int vrc = VINF_SUCCESS; + + bool fDryrun = false; + std::vector< Utf8Str > vecSources; + const char *pszDst = NULL; + com::SafeArray<FsObjRenameFlag_T> aRenameFlags; + + try + { + /** @todo Make flags configurable. */ + aRenameFlags.push_back(FsObjRenameFlag_NoReplace); + + while ( (ch = RTGetOpt(&GetState, &ValueUnion)) + && RT_SUCCESS(vrc)) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + /** @todo Implement a --dryrun command. */ + /** @todo Implement rename flags. */ + + case VINF_GETOPT_NOT_OPTION: + vecSources.push_back(Utf8Str(ValueUnion.psz)); + pszDst = ValueUnion.psz; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + } + catch (std::bad_alloc &) + { + vrc = VERR_NO_MEMORY; + } + + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Failed to initialize, vrc=%Rrc\n"), vrc); + + size_t cSources = vecSources.size(); + if (!cSources) + return errorSyntax(GuestCtrl::tr("No source(s) to move specified!")); + if (cSources < 2) + return errorSyntax(GuestCtrl::tr("No destination specified!")); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + /* Delete last element, which now is the destination. */ + vecSources.pop_back(); + cSources = vecSources.size(); + + HRESULT hrc = S_OK; + + /* Destination must be a directory when specifying multiple sources. */ + if (cSources > 1) + { + ComPtr<IGuestFsObjInfo> pFsObjInfo; + hrc = pCtx->pGuestSession->FsObjQueryInfo(Bstr(pszDst).raw(), FALSE /*followSymlinks*/, pFsObjInfo.asOutParam()); + if (FAILED(hrc)) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Destination does not exist\n")); + } + else + { + FsObjType_T enmObjType = FsObjType_Unknown; /* Shut up MSC */ + hrc = pFsObjInfo->COMGETTER(Type)(&enmObjType); + if (SUCCEEDED(hrc)) + { + if (enmObjType != FsObjType_Directory) + return RTMsgErrorExit(RTEXITCODE_FAILURE, + GuestCtrl::tr("Destination must be a directory when specifying multiple sources\n")); + } + else + return RTMsgErrorExit(RTEXITCODE_FAILURE, + GuestCtrl::tr("Unable to determine destination type: %Rhrc\n"), + hrc); + } + } + + /* + * Rename (move) the entries. + */ + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Renaming %RU32 %s ...\n"), cSources, + cSources > 1 ? GuestCtrl::tr("sources", "", cSources) : GuestCtrl::tr("source")); + + std::vector< Utf8Str >::iterator it = vecSources.begin(); + while ( it != vecSources.end() + && !g_fGuestCtrlCanceled) + { + Utf8Str strSrcCur = (*it); + + ComPtr<IGuestFsObjInfo> pFsObjInfo; + FsObjType_T enmObjType = FsObjType_Unknown; /* Shut up MSC */ + hrc = pCtx->pGuestSession->FsObjQueryInfo(Bstr(strSrcCur).raw(), FALSE /*followSymlinks*/, pFsObjInfo.asOutParam()); + if (SUCCEEDED(hrc)) + hrc = pFsObjInfo->COMGETTER(Type)(&enmObjType); + if (FAILED(hrc)) + { + RTPrintf(GuestCtrl::tr("Cannot stat \"%s\": No such file or directory\n"), strSrcCur.c_str()); + ++it; + continue; /* Skip. */ + } + + char *pszDstCur = NULL; + + if (cSources > 1) + { + pszDstCur = RTPathJoinA(pszDst, RTPathFilename(strSrcCur.c_str())); + } + else + pszDstCur = RTStrDup(pszDst); + + AssertPtrBreakStmt(pszDstCur, VERR_NO_MEMORY); + + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Renaming %s \"%s\" to \"%s\" ...\n"), + enmObjType == FsObjType_Directory ? GuestCtrl::tr("directory", "object") : GuestCtrl::tr("file","object"), + strSrcCur.c_str(), pszDstCur); + + if (!fDryrun) + { + CHECK_ERROR(pCtx->pGuestSession, FsObjRename(Bstr(strSrcCur).raw(), + Bstr(pszDstCur).raw(), + ComSafeArrayAsInParam(aRenameFlags))); + /* Keep going with next item in case of errors. */ + } + + RTStrFree(pszDstCur); + + ++it; + } + + if ( (it != vecSources.end()) + && pCtx->cVerbose) + { + RTPrintf(GuestCtrl::tr("Warning: Not all sources were renamed\n")); + } + + return FAILED(hrc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleMkTemp(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--mode", 'm', RTGETOPT_REQ_UINT32 }, + { "--directory", 'D', RTGETOPT_REQ_NOTHING }, + { "--secure", 's', RTGETOPT_REQ_NOTHING }, + { "--tmpdir", 't', RTGETOPT_REQ_STRING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + Utf8Str strTemplate; + uint32_t fMode = 0; /* Default mode. */ + bool fDirectory = false; + bool fSecure = false; + Utf8Str strTempDir; + + DESTDIRMAP mapDirs; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'm': /* Mode */ + fMode = ValueUnion.u32; + break; + + case 'D': /* Create directory */ + fDirectory = true; + break; + + case 's': /* Secure */ + fSecure = true; + break; + + case 't': /* Temp directory */ + strTempDir = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + if (strTemplate.isEmpty()) + strTemplate = ValueUnion.psz; + else + return errorSyntax(GuestCtrl::tr("More than one template specified!\n")); + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (strTemplate.isEmpty()) + return errorSyntax(GuestCtrl::tr("No template specified!")); + + if (!fDirectory) + return errorSyntax(GuestCtrl::tr("Creating temporary files is currently not supported!")); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + /* + * Create the directories. + */ + if (pCtx->cVerbose) + { + if (fDirectory && !strTempDir.isEmpty()) + RTPrintf(GuestCtrl::tr("Creating temporary directory from template '%s' in directory '%s' ...\n"), + strTemplate.c_str(), strTempDir.c_str()); + else if (fDirectory) + RTPrintf(GuestCtrl::tr("Creating temporary directory from template '%s' in default temporary directory ...\n"), + strTemplate.c_str()); + else if (!fDirectory && !strTempDir.isEmpty()) + RTPrintf(GuestCtrl::tr("Creating temporary file from template '%s' in directory '%s' ...\n"), + strTemplate.c_str(), strTempDir.c_str()); + else if (!fDirectory) + RTPrintf(GuestCtrl::tr("Creating temporary file from template '%s' in default temporary directory ...\n"), + strTemplate.c_str()); + } + + HRESULT hrc = S_OK; + if (fDirectory) + { + Bstr bstrDirectory; + CHECK_ERROR(pCtx->pGuestSession, DirectoryCreateTemp(Bstr(strTemplate).raw(), + fMode, Bstr(strTempDir).raw(), + fSecure, + bstrDirectory.asOutParam())); + if (SUCCEEDED(hrc)) + RTPrintf(GuestCtrl::tr("Directory name: %ls\n"), bstrDirectory.raw()); + } + else + { + // else - temporary file not yet implemented + /** @todo implement temporary file creation (we fend it off above, no + * worries). */ + hrc = E_FAIL; + } + + return FAILED(hrc) ? RTEXITCODE_FAILURE : RTEXITCODE_SUCCESS; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleStat(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--dereference", 'L', RTGETOPT_REQ_NOTHING }, + { "--file-system", 'f', RTGETOPT_REQ_NOTHING }, + { "--format", 'c', RTGETOPT_REQ_STRING }, + { "--terse", 't', RTGETOPT_REQ_NOTHING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + while ( (ch = RTGetOpt(&GetState, &ValueUnion)) != 0 + && ch != VINF_GETOPT_NOT_OPTION) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'L': /* Dereference */ + case 'f': /* File-system */ + case 'c': /* Format */ + case 't': /* Terse */ + return errorSyntax(GuestCtrl::tr("Command \"%s\" not implemented yet!"), ValueUnion.psz); + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (ch != VINF_GETOPT_NOT_OPTION) + return errorSyntax(GuestCtrl::tr("Nothing to stat!")); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + + /* + * Do the file stat'ing. + */ + while (ch == VINF_GETOPT_NOT_OPTION) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Checking for element \"%s\" ...\n"), ValueUnion.psz); + + ComPtr<IGuestFsObjInfo> pFsObjInfo; + HRESULT hrc = pCtx->pGuestSession->FsObjQueryInfo(Bstr(ValueUnion.psz).raw(), FALSE /*followSymlinks*/, + pFsObjInfo.asOutParam()); + if (FAILED(hrc)) + { + /** @todo r=bird: There might be other reasons why we end up here than + * non-existing "element" (object or file, please, nobody calls it elements). */ + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Failed to stat '%s': No such file\n"), ValueUnion.psz); + rcExit = RTEXITCODE_FAILURE; + } + else + { + RTPrintf(GuestCtrl::tr(" File: '%s'\n"), ValueUnion.psz); /** @todo escape this name. */ + + FsObjType_T enmType = FsObjType_Unknown; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(Type)(&enmType)); + LONG64 cbObject = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(ObjectSize)(&cbObject)); + LONG64 cbAllocated = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(AllocatedSize)(&cbAllocated)); + LONG uid = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(UID)(&uid)); + LONG gid = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(GID)(&gid)); + Bstr bstrUsername; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(UserName)(bstrUsername.asOutParam())); + Bstr bstrGroupName; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(GroupName)(bstrGroupName.asOutParam())); + Bstr bstrAttribs; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(FileAttributes)(bstrAttribs.asOutParam())); + LONG64 idNode = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(NodeId)(&idNode)); + ULONG uDevNode = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(NodeIdDevice)(&uDevNode)); + ULONG uDeviceNo = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(DeviceNumber)(&uDeviceNo)); + ULONG cHardLinks = 1; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(HardLinks)(&cHardLinks)); + LONG64 nsBirthTime = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(BirthTime)(&nsBirthTime)); + LONG64 nsChangeTime = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(ChangeTime)(&nsChangeTime)); + LONG64 nsModificationTime = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(ModificationTime)(&nsModificationTime)); + LONG64 nsAccessTime = 0; + CHECK_ERROR2I(pFsObjInfo, COMGETTER(AccessTime)(&nsAccessTime)); + + RTPrintf(GuestCtrl::tr(" Size: %-17RU64 Alloc: %-19RU64 Type: %s\n"), + cbObject, cbAllocated, gctlFsObjTypeToName(enmType)); + RTPrintf(GuestCtrl::tr("Device: %#-17RX32 INode: %-18RU64 Links: %u\n"), uDevNode, idNode, cHardLinks); + + Utf8Str strAttrib(bstrAttribs); + char *pszMode = strAttrib.mutableRaw(); + char *pszAttribs = strchr(pszMode, ' '); + if (pszAttribs) + do *pszAttribs++ = '\0'; + while (*pszAttribs == ' '); + else + pszAttribs = strchr(pszMode, '\0'); + if (uDeviceNo != 0) + RTPrintf(GuestCtrl::tr(" Mode: %-16s Attrib: %-17s Dev ID: %#RX32\n"), pszMode, pszAttribs, uDeviceNo); + else + RTPrintf(GuestCtrl::tr(" Mode: %-16s Attrib: %s\n"), pszMode, pszAttribs); + + RTPrintf(GuestCtrl::tr(" Owner: %4d/%-12ls Group: %4d/%ls\n"), uid, bstrUsername.raw(), gid, bstrGroupName.raw()); + + RTTIMESPEC TimeSpec; + char szTmp[RTTIME_STR_LEN]; + RTPrintf(GuestCtrl::tr(" Birth: %s\n"), RTTimeSpecToString(RTTimeSpecSetNano(&TimeSpec, nsBirthTime), + szTmp, sizeof(szTmp))); + RTPrintf(GuestCtrl::tr("Change: %s\n"), RTTimeSpecToString(RTTimeSpecSetNano(&TimeSpec, nsChangeTime), + szTmp, sizeof(szTmp))); + RTPrintf(GuestCtrl::tr("Modify: %s\n"), RTTimeSpecToString(RTTimeSpecSetNano(&TimeSpec, nsModificationTime), + szTmp, sizeof(szTmp))); + RTPrintf(GuestCtrl::tr("Access: %s\n"), RTTimeSpecToString(RTTimeSpecSetNano(&TimeSpec, nsAccessTime), + szTmp, sizeof(szTmp))); + + /* Skiping: Generation ID - only the ISO9660 VFS sets this. FreeBSD user flags. */ + } + + /* Next file. */ + ch = RTGetOpt(&GetState, &ValueUnion); + } + + return rcExit; +} + +/** + * Waits for a Guest Additions run level being reached. + * + * @returns VBox status code. + * Returns VERR_CANCELLED if waiting for cancelled due to signal handling, e.g. when CTRL+C or some sort was pressed. + * @param pCtx The guest control command context. + * @param enmRunLevel Run level to wait for. + * @param cMsTimeout Timeout (in ms) for waiting. + */ +static int gctlWaitForRunLevel(PGCTLCMDCTX pCtx, AdditionsRunLevelType_T enmRunLevel, RTMSINTERVAL cMsTimeout) +{ + int vrc = VINF_SUCCESS; /* Shut up MSVC. */ + + try + { + HRESULT hrc = S_OK; + /** Whether we need to actually wait for the run level or if we already reached it. */ + bool fWait = false; + + /* Install an event handler first to catch any runlevel changes. */ + ComObjPtr<GuestAdditionsRunlevelListenerImpl> pGuestListener; + do + { + /* Listener creation. */ + pGuestListener.createObject(); + pGuestListener->init(new GuestAdditionsRunlevelListener(enmRunLevel)); + + /* Register for IGuest events. */ + ComPtr<IEventSource> es; + CHECK_ERROR_BREAK(pCtx->pGuest, COMGETTER(EventSource)(es.asOutParam())); + com::SafeArray<VBoxEventType_T> eventTypes; + eventTypes.push_back(VBoxEventType_OnGuestAdditionsStatusChanged); + CHECK_ERROR_BREAK(es, RegisterListener(pGuestListener, ComSafeArrayAsInParam(eventTypes), + true /* Active listener */)); + + AdditionsRunLevelType_T enmRunLevelCur = AdditionsRunLevelType_None; + CHECK_ERROR_BREAK(pCtx->pGuest, COMGETTER(AdditionsRunLevel)(&enmRunLevelCur)); + fWait = enmRunLevelCur != enmRunLevel; + + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Current run level is %RU32\n"), enmRunLevelCur); + + } while (0); + + if (fWait) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Waiting for run level %RU32 ...\n"), enmRunLevel); + + RTMSINTERVAL tsStart = RTTimeMilliTS(); + while (RTTimeMilliTS() - tsStart < cMsTimeout) + { + /* Wait for the global signal semaphore getting signalled. */ + vrc = RTSemEventWait(g_SemEventGuestCtrlCanceled, 100 /* ms */); + if (RT_FAILURE(vrc)) + { + if (vrc == VERR_TIMEOUT) + continue; + else + { + RTPrintf(GuestCtrl::tr("Waiting failed with %Rrc\n"), vrc); + break; + } + } + else if (pCtx->cVerbose) + { + RTPrintf(GuestCtrl::tr("Run level %RU32 reached\n"), enmRunLevel); + break; + } + + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + } + + if ( vrc == VERR_TIMEOUT + && pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Run level %RU32 not reached within time\n"), enmRunLevel); + } + + if (!pGuestListener.isNull()) + { + /* Guest callback unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR(pCtx->pGuest, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR(pES, UnregisterListener(pGuestListener)); + pGuestListener.setNull(); + } + + if (g_fGuestCtrlCanceled) + vrc = VERR_CANCELLED; + } + catch (std::bad_alloc &) + { + vrc = VERR_NO_MEMORY; + } + + return vrc; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleUpdateAdditions(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + /** Timeout to wait for the whole updating procedure to complete. */ + uint32_t cMsTimeout = RT_INDEFINITE_WAIT; + /** Source path to .ISO Guest Additions file to use. */ + Utf8Str strSource; + com::SafeArray<IN_BSTR> aArgs; + /** Whether to reboot the guest automatically when the update process has finished successfully. */ + bool fRebootOnFinish = false; + /** Whether to only wait for getting the update process started instead of waiting until it finishes. */ + bool fWaitStartOnly = false; + /** Whether to wait for the VM being ready to start the update. Needs Guest Additions facility reporting. */ + bool fWaitReady = false; + /** Whether to verify if the Guest Additions were successfully updated on the guest. */ + bool fVerify = false; + + /* + * Parse arguments. + */ + enum KGSTCTRLUPDATEADDITIONSOPT + { + KGSTCTRLUPDATEADDITIONSOPT_REBOOT = 1000, + KGSTCTRLUPDATEADDITIONSOPT_SOURCE, + KGSTCTRLUPDATEADDITIONSOPT_TIMEOUT, + KGSTCTRLUPDATEADDITIONSOPT_VERIFY, + KGSTCTRLUPDATEADDITIONSOPT_WAITREADY, + KGSTCTRLUPDATEADDITIONSOPT_WAITSTART + }; + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--reboot", KGSTCTRLUPDATEADDITIONSOPT_REBOOT, RTGETOPT_REQ_NOTHING }, + { "--source", KGSTCTRLUPDATEADDITIONSOPT_SOURCE, RTGETOPT_REQ_STRING }, + { "--timeout", KGSTCTRLUPDATEADDITIONSOPT_TIMEOUT, RTGETOPT_REQ_UINT32 }, + { "--verify", KGSTCTRLUPDATEADDITIONSOPT_VERIFY, RTGETOPT_REQ_NOTHING }, + { "--wait-ready", KGSTCTRLUPDATEADDITIONSOPT_WAITREADY, RTGETOPT_REQ_NOTHING }, + { "--wait-start", KGSTCTRLUPDATEADDITIONSOPT_WAITSTART, RTGETOPT_REQ_NOTHING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + int vrc = VINF_SUCCESS; + while ( (ch = RTGetOpt(&GetState, &ValueUnion)) + && RT_SUCCESS(vrc)) + { + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case KGSTCTRLUPDATEADDITIONSOPT_REBOOT: + fRebootOnFinish = true; + break; + + case KGSTCTRLUPDATEADDITIONSOPT_SOURCE: + vrc = RTPathAbsCxx(strSource, ValueUnion.psz); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(GuestCtrl::tr("RTPathAbsCxx failed on '%s': %Rrc"), ValueUnion.psz, vrc); + break; + + case KGSTCTRLUPDATEADDITIONSOPT_WAITSTART: + fWaitStartOnly = true; + break; + + case KGSTCTRLUPDATEADDITIONSOPT_WAITREADY: + fWaitReady = true; + break; + + case KGSTCTRLUPDATEADDITIONSOPT_VERIFY: + fVerify = true; + fRebootOnFinish = true; /* Verification needs a mandatory reboot after successful update. */ + break; + + case VINF_GETOPT_NOT_OPTION: + if (aArgs.size() == 0 && strSource.isEmpty()) + strSource = ValueUnion.psz; + else + aArgs.push_back(Bstr(ValueUnion.psz).raw()); + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Updating Guest Additions ...\n")); + + HRESULT hrc = S_OK; + while (strSource.isEmpty()) + { + ComPtr<ISystemProperties> pProperties; + CHECK_ERROR_BREAK(pCtx->pArg->virtualBox, COMGETTER(SystemProperties)(pProperties.asOutParam())); + Bstr strISO; + CHECK_ERROR_BREAK(pProperties, COMGETTER(DefaultAdditionsISO)(strISO.asOutParam())); + strSource = strISO; + break; + } + + /* Determine source if not set yet. */ + if (strSource.isEmpty()) + { + RTMsgError(GuestCtrl::tr("No Guest Additions source found or specified, aborting\n")); + vrc = VERR_FILE_NOT_FOUND; + } + else if (!RTFileExists(strSource.c_str())) + { + RTMsgError(GuestCtrl::tr("Source \"%s\" does not exist!\n"), strSource.c_str()); + vrc = VERR_FILE_NOT_FOUND; + } + + + +#if 0 + ComPtr<IGuest> guest; + HRESULT hrc = pConsole->COMGETTER(Guest)(guest.asOutParam()); + if (SUCCEEDED(hrc) && !guest.isNull()) + { + SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", GuestCtrl::tr("OS type:")); + + AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */ + hrc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel); + if (SUCCEEDED(hrc)) + SHOW_ULONG_VALUE("GuestAdditionsRunLevel", GuestCtrl::tr("Additions run level:"), (ULONG)guestRunLevel, ""); + + Bstr guestString; + hrc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam()); + if ( SUCCEEDED(hrc) + && !guestString.isEmpty()) + { + ULONG uRevision; + hrc = guest->COMGETTER(AdditionsRevision)(&uRevision); + if (FAILED(hrc)) + uRevision = 0; + RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision); + SHOW_UTF8_STRING("GuestAdditionsVersion", GuestCtrl::tr("Additions version:"), szValue); + } + } +#endif + + if (RT_SUCCESS(vrc)) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Using source: %s\n"), strSource.c_str()); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + if (fWaitReady) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Waiting for current Guest Additions inside VM getting ready for updating ...\n")); + + const uint64_t uTsStart = RTTimeMilliTS(); + vrc = gctlWaitForRunLevel(pCtx, AdditionsRunLevelType_Userland, cMsTimeout); + if (RT_SUCCESS(vrc)) + cMsTimeout = cMsTimeout != RT_INDEFINITE_WAIT ? cMsTimeout - (RTTimeMilliTS() - uTsStart) : cMsTimeout; + } + + if (RT_SUCCESS(vrc)) + { + /* Get current Guest Additions version / revision. */ + Bstr strGstVerCur; + ULONG uGstRevCur = 0; + hrc = pCtx->pGuest->COMGETTER(AdditionsVersion)(strGstVerCur.asOutParam()); + if ( SUCCEEDED(hrc) + && !strGstVerCur.isEmpty()) + { + hrc = pCtx->pGuest->COMGETTER(AdditionsRevision)(&uGstRevCur); + if (SUCCEEDED(hrc)) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Guest Additions %lsr%RU64 currently installed, waiting for Guest Additions installer to start ...\n"), + strGstVerCur.raw(), uGstRevCur); + } + } + + com::SafeArray<AdditionsUpdateFlag_T> aUpdateFlags; + if (fWaitStartOnly) + aUpdateFlags.push_back(AdditionsUpdateFlag_WaitForUpdateStartOnly); + + ComPtr<IProgress> pProgress; + CHECK_ERROR(pCtx->pGuest, UpdateGuestAdditions(Bstr(strSource).raw(), + ComSafeArrayAsInParam(aArgs), + ComSafeArrayAsInParam(aUpdateFlags), + pProgress.asOutParam())); + if (FAILED(hrc)) + vrc = gctlPrintError(pCtx->pGuest, COM_IIDOF(IGuest)); + else + { + if (pCtx->cVerbose) + hrc = showProgress(pProgress); + else + hrc = pProgress->WaitForCompletion((int32_t)cMsTimeout); + + if (SUCCEEDED(hrc)) + CHECK_PROGRESS_ERROR(pProgress, (GuestCtrl::tr("Guest Additions update failed"))); + vrc = gctlPrintProgressError(pProgress); + if (RT_SUCCESS(vrc)) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Guest Additions update successful.\n")); + + if (fRebootOnFinish) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Rebooting guest ...\n")); + com::SafeArray<GuestShutdownFlag_T> aShutdownFlags; + aShutdownFlags.push_back(GuestShutdownFlag_Reboot); + CHECK_ERROR(pCtx->pGuest, Shutdown(ComSafeArrayAsInParam(aShutdownFlags))); + if (FAILED(hrc)) + { + if (hrc == VBOX_E_NOT_SUPPORTED) + { + RTPrintf(GuestCtrl::tr("Current installed Guest Additions don't support automatic rebooting. " + "Please reboot manually.\n")); + vrc = VERR_NOT_SUPPORTED; + } + else + vrc = gctlPrintError(pCtx->pGuest, COM_IIDOF(IGuest)); + } + else + { + if (fWaitReady) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Waiting for new Guest Additions inside VM getting ready ...\n")); + + vrc = gctlWaitForRunLevel(pCtx, AdditionsRunLevelType_Userland, cMsTimeout); + if (RT_SUCCESS(vrc)) + { + if (fVerify) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Verifying Guest Additions update ...\n")); + + /* Get new Guest Additions version / revision. */ + Bstr strGstVerNew; + ULONG uGstRevNew = 0; + hrc = pCtx->pGuest->COMGETTER(AdditionsVersion)(strGstVerNew.asOutParam()); + if ( SUCCEEDED(hrc) + && !strGstVerNew.isEmpty()) + { + hrc = pCtx->pGuest->COMGETTER(AdditionsRevision)(&uGstRevNew); + if (FAILED(hrc)) + uGstRevNew = 0; + } + + /** @todo Do more verification here. */ + vrc = uGstRevNew > uGstRevCur ? VINF_SUCCESS : VERR_NO_CHANGE; + + if (pCtx->cVerbose) + { + RTPrintf(GuestCtrl::tr("Old Guest Additions: %ls%RU64\n"), strGstVerCur.raw(), + uGstRevCur); + RTPrintf(GuestCtrl::tr("New Guest Additions: %ls%RU64\n"), strGstVerNew.raw(), + uGstRevNew); + + if (RT_FAILURE(vrc)) + { + RTPrintf(GuestCtrl::tr("\nError updating Guest Additions, please check guest installer log\n")); + } + else + { + if (uGstRevNew < uGstRevCur) + RTPrintf(GuestCtrl::tr("\nWARNING: Guest Additions were downgraded\n")); + } + } + } + } + } + else if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("The guest needs to be restarted in order to make use of the updated Guest Additions.\n")); + } + } + } + } + } + } + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * Returns a Guest Additions run level from a string. + * + * @returns Run level if found, or AdditionsRunLevelType_None if not found / invalid. + * @param pcszStr String to return run level for. + */ +static AdditionsRunLevelType_T gctlGetRunLevelFromStr(const char *pcszStr) +{ + AssertPtrReturn(pcszStr, AdditionsRunLevelType_None); + + if (RTStrICmp(pcszStr, "system") == 0) return AdditionsRunLevelType_System; + else if (RTStrICmp(pcszStr, "userland") == 0) return AdditionsRunLevelType_Userland; + else if (RTStrICmp(pcszStr, "desktop") == 0) return AdditionsRunLevelType_Desktop; + + return AdditionsRunLevelType_None; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleWaitRunLevel(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + /** Timeout to wait for run level being reached. + * By default we wait until it's reached. */ + uint32_t cMsTimeout = RT_INDEFINITE_WAIT; + + /* + * Parse arguments. + */ + enum KGSTCTRLWAITRUNLEVELOPT + { + KGSTCTRLWAITRUNLEVELOPT_TIMEOUT = 1000 + }; + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--timeout", KGSTCTRLWAITRUNLEVELOPT_TIMEOUT, RTGETOPT_REQ_UINT32 } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + AdditionsRunLevelType_T enmRunLevel = AdditionsRunLevelType_None; + + int vrc = VINF_SUCCESS; + while ( (ch = RTGetOpt(&GetState, &ValueUnion)) + && RT_SUCCESS(vrc)) + { + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case KGSTCTRLWAITRUNLEVELOPT_TIMEOUT: + cMsTimeout = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + { + enmRunLevel = gctlGetRunLevelFromStr(ValueUnion.psz); + if (enmRunLevel == AdditionsRunLevelType_None) + return errorSyntax(GuestCtrl::tr("Invalid run level specified. Valid values are: system, userland, desktop")); + break; + } + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + if (enmRunLevel == AdditionsRunLevelType_None) + return errorSyntax(GuestCtrl::tr("Missing run level to wait for")); + + vrc = gctlWaitForRunLevel(pCtx, enmRunLevel, cMsTimeout); + + return RT_SUCCESS(vrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleList(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + bool fSeenListArg = false; + bool fListAll = false; + bool fListSessions = false; + bool fListProcesses = false; + bool fListFiles = false; + + int vrc = VINF_SUCCESS; + while ( (ch = RTGetOpt(&GetState, &ValueUnion)) + && RT_SUCCESS(vrc)) + { + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case VINF_GETOPT_NOT_OPTION: + if ( !RTStrICmp(ValueUnion.psz, "sessions") + || !RTStrICmp(ValueUnion.psz, "sess")) + fListSessions = true; + else if ( !RTStrICmp(ValueUnion.psz, "processes") + || !RTStrICmp(ValueUnion.psz, "procs")) + fListSessions = fListProcesses = true; /* Showing processes implies showing sessions. */ + else if (!RTStrICmp(ValueUnion.psz, "files")) + fListSessions = fListFiles = true; /* Showing files implies showing sessions. */ + else if (!RTStrICmp(ValueUnion.psz, "all")) + fListAll = true; + else + return errorSyntax(GuestCtrl::tr("Unknown list: '%s'"), ValueUnion.psz); + fSeenListArg = true; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (!fSeenListArg) + return errorSyntax(GuestCtrl::tr("Missing list name")); + Assert(fListAll || fListSessions); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + + /** @todo Do we need a machine-readable output here as well? */ + + HRESULT hrc; + size_t cTotalProcs = 0; + size_t cTotalFiles = 0; + + SafeIfaceArray <IGuestSession> collSessions; + CHECK_ERROR(pCtx->pGuest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions))); + if (SUCCEEDED(hrc)) + { + size_t const cSessions = collSessions.size(); + if (cSessions) + { + RTPrintf(GuestCtrl::tr("Active guest sessions:\n")); + + /** @todo Make this output a bit prettier. No time now. */ + + for (size_t i = 0; i < cSessions; i++) + { + ComPtr<IGuestSession> pCurSession = collSessions[i]; + if (!pCurSession.isNull()) + { + do + { + ULONG uID; + CHECK_ERROR_BREAK(pCurSession, COMGETTER(Id)(&uID)); + Bstr strName; + CHECK_ERROR_BREAK(pCurSession, COMGETTER(Name)(strName.asOutParam())); + Bstr strUser; + CHECK_ERROR_BREAK(pCurSession, COMGETTER(User)(strUser.asOutParam())); + GuestSessionStatus_T sessionStatus; + CHECK_ERROR_BREAK(pCurSession, COMGETTER(Status)(&sessionStatus)); + RTPrintf(GuestCtrl::tr("\n\tSession #%-3zu ID=%-3RU32 User=%-16ls Status=[%s] Name=%ls"), + i, uID, strUser.raw(), gctlGuestSessionStatusToText(sessionStatus), strName.raw()); + } while (0); + + if ( fListAll + || fListProcesses) + { + SafeIfaceArray <IGuestProcess> collProcesses; + CHECK_ERROR_BREAK(pCurSession, COMGETTER(Processes)(ComSafeArrayAsOutParam(collProcesses))); + for (size_t a = 0; a < collProcesses.size(); a++) + { + ComPtr<IGuestProcess> pCurProcess = collProcesses[a]; + if (!pCurProcess.isNull()) + { + do + { + ULONG uPID; + CHECK_ERROR_BREAK(pCurProcess, COMGETTER(PID)(&uPID)); + Bstr strExecPath; + CHECK_ERROR_BREAK(pCurProcess, COMGETTER(ExecutablePath)(strExecPath.asOutParam())); + ProcessStatus_T procStatus; + CHECK_ERROR_BREAK(pCurProcess, COMGETTER(Status)(&procStatus)); + + RTPrintf(GuestCtrl::tr("\n\t\tProcess #%-03zu PID=%-6RU32 Status=[%s] Command=%ls"), + a, uPID, gctlProcessStatusToText(procStatus), strExecPath.raw()); + } while (0); + } + } + + cTotalProcs += collProcesses.size(); + } + + if ( fListAll + || fListFiles) + { + SafeIfaceArray <IGuestFile> collFiles; + CHECK_ERROR_BREAK(pCurSession, COMGETTER(Files)(ComSafeArrayAsOutParam(collFiles))); + for (size_t a = 0; a < collFiles.size(); a++) + { + ComPtr<IGuestFile> pCurFile = collFiles[a]; + if (!pCurFile.isNull()) + { + do + { + ULONG idFile; + CHECK_ERROR_BREAK(pCurFile, COMGETTER(Id)(&idFile)); + Bstr strName; + CHECK_ERROR_BREAK(pCurFile, COMGETTER(Filename)(strName.asOutParam())); + FileStatus_T fileStatus; + CHECK_ERROR_BREAK(pCurFile, COMGETTER(Status)(&fileStatus)); + + RTPrintf(GuestCtrl::tr("\n\t\tFile #%-03zu ID=%-6RU32 Status=[%s] Name=%ls"), + a, idFile, gctlFileStatusToText(fileStatus), strName.raw()); + } while (0); + } + } + + cTotalFiles += collFiles.size(); + } + } + } + + RTPrintf(GuestCtrl::tr("\n\nTotal guest sessions: %zu\n"), collSessions.size()); + if (fListAll || fListProcesses) + RTPrintf(GuestCtrl::tr("Total guest processes: %zu\n"), cTotalProcs); + if (fListAll || fListFiles) + RTPrintf(GuestCtrl::tr("Total guest files: %zu\n"), cTotalFiles); + } + else + RTPrintf(GuestCtrl::tr("No active guest sessions found\n")); + } + + if (FAILED(hrc)) /** @todo yeah, right... Only the last error? */ + rcExit = RTEXITCODE_FAILURE; + + return rcExit; +} + +static DECLCALLBACK(RTEXITCODE) gctlHandleCloseProcess(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--session-id", 'i', RTGETOPT_REQ_UINT32 }, + { "--session-name", 'n', RTGETOPT_REQ_STRING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + std::vector < uint32_t > vecPID; + ULONG idSession = UINT32_MAX; + Utf8Str strSessionName; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'n': /* Session name (or pattern) */ + strSessionName = ValueUnion.psz; + break; + + case 'i': /* Session ID */ + idSession = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + { + /* Treat every else specified as a PID to kill. */ + uint32_t uPid; + vrc = RTStrToUInt32Ex(ValueUnion.psz, NULL, 0, &uPid); + if ( RT_SUCCESS(vrc) + && vrc != VWRN_TRAILING_CHARS + && vrc != VWRN_NUMBER_TOO_BIG + && vrc != VWRN_NEGATIVE_UNSIGNED) + { + if (uPid != 0) + { + try + { + vecPID.push_back(uPid); + } + catch (std::bad_alloc &) + { + return RTMsgErrorExit(RTEXITCODE_FAILURE, GuestCtrl::tr("Out of memory")); + } + } + else + return errorSyntax(GuestCtrl::tr("Invalid PID value: 0")); + } + else + return errorSyntax(GuestCtrl::tr("Error parsing PID value: %Rrc"), vrc); + break; + } + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if (vecPID.empty()) + return errorSyntax(GuestCtrl::tr("At least one PID must be specified to kill!")); + + if ( strSessionName.isEmpty() + && idSession == UINT32_MAX) + return errorSyntax(GuestCtrl::tr("No session ID specified!")); + + if ( strSessionName.isNotEmpty() + && idSession != UINT32_MAX) + return errorSyntax(GuestCtrl::tr("Either session ID or name (pattern) must be specified")); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + HRESULT hrc = S_OK; + + ComPtr<IGuestSession> pSession; + ComPtr<IGuestProcess> pProcess; + do + { + uint32_t uProcsTerminated = 0; + + SafeIfaceArray <IGuestSession> collSessions; + CHECK_ERROR_BREAK(pCtx->pGuest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions))); + size_t cSessions = collSessions.size(); + + uint32_t cSessionsHandled = 0; + for (size_t i = 0; i < cSessions; i++) + { + pSession = collSessions[i]; + Assert(!pSession.isNull()); + + ULONG uID; /* Session ID */ + CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID)); + Bstr strName; + CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam())); + Utf8Str strNameUtf8(strName); /* Session name */ + + bool fSessionFound; + if (strSessionName.isEmpty()) /* Search by ID. Slow lookup. */ + fSessionFound = uID == idSession; + else /* ... or by naming pattern. */ + fSessionFound = RTStrSimplePatternMatch(strSessionName.c_str(), strNameUtf8.c_str()); + if (fSessionFound) + { + AssertStmt(!pSession.isNull(), break); + cSessionsHandled++; + + SafeIfaceArray <IGuestProcess> collProcs; + CHECK_ERROR_BREAK(pSession, COMGETTER(Processes)(ComSafeArrayAsOutParam(collProcs))); + + size_t cProcs = collProcs.size(); + for (size_t p = 0; p < cProcs; p++) + { + pProcess = collProcs[p]; + Assert(!pProcess.isNull()); + + ULONG uPID; /* Process ID */ + CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID)); + + bool fProcFound = false; + for (size_t a = 0; a < vecPID.size(); a++) /* Slow, but works. */ + { + fProcFound = vecPID[a] == uPID; + if (fProcFound) + break; + } + + if (fProcFound) + { + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Terminating process (PID %RU32) (session ID %RU32) ...\n"), + uPID, uID); + CHECK_ERROR_BREAK(pProcess, Terminate()); + uProcsTerminated++; + } + else + { + if (idSession != UINT32_MAX) + RTPrintf(GuestCtrl::tr("No matching process(es) for session ID %RU32 found\n"), + idSession); + } + + pProcess.setNull(); + } + + pSession.setNull(); + } + } + + if (!cSessionsHandled) + RTPrintf(GuestCtrl::tr("No matching session(s) found\n")); + + if (uProcsTerminated) + RTPrintf(GuestCtrl::tr("%RU32 process(es) terminated\n", "", uProcsTerminated), uProcsTerminated); + + } while (0); + + pProcess.setNull(); + pSession.setNull(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static DECLCALLBACK(RTEXITCODE) gctlHandleCloseSession(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + enum GETOPTDEF_SESSIONCLOSE + { + GETOPTDEF_SESSIONCLOSE_ALL = 2000 + }; + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--all", GETOPTDEF_SESSIONCLOSE_ALL, RTGETOPT_REQ_NOTHING }, + { "--session-id", 'i', RTGETOPT_REQ_UINT32 }, + { "--session-name", 'n', RTGETOPT_REQ_STRING } + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + ULONG idSession = UINT32_MAX; + Utf8Str strSessionName; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 'n': /* Session name pattern */ + strSessionName = ValueUnion.psz; + break; + + case 'i': /* Session ID */ + idSession = ValueUnion.u32; + break; + + case GETOPTDEF_SESSIONCLOSE_ALL: + strSessionName = "*"; + break; + + case VINF_GETOPT_NOT_OPTION: + /** @todo Supply a CSV list of IDs or patterns to close? + * break; */ + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + if ( strSessionName.isEmpty() + && idSession == UINT32_MAX) + return errorSyntax(GuestCtrl::tr("No session ID specified!")); + + if ( !strSessionName.isEmpty() + && idSession != UINT32_MAX) + return errorSyntax(GuestCtrl::tr("Either session ID or name (pattern) must be specified")); + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + HRESULT hrc = S_OK; + + do + { + size_t cSessionsHandled = 0; + + SafeIfaceArray <IGuestSession> collSessions; + CHECK_ERROR_BREAK(pCtx->pGuest, COMGETTER(Sessions)(ComSafeArrayAsOutParam(collSessions))); + size_t cSessions = collSessions.size(); + + for (size_t i = 0; i < cSessions; i++) + { + ComPtr<IGuestSession> pSession = collSessions[i]; + Assert(!pSession.isNull()); + + ULONG uID; /* Session ID */ + CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID)); + Bstr strName; + CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam())); + Utf8Str strNameUtf8(strName); /* Session name */ + + bool fSessionFound; + if (strSessionName.isEmpty()) /* Search by ID. Slow lookup. */ + fSessionFound = uID == idSession; + else /* ... or by naming pattern. */ + fSessionFound = RTStrSimplePatternMatch(strSessionName.c_str(), strNameUtf8.c_str()); + if (fSessionFound) + { + cSessionsHandled++; + + Assert(!pSession.isNull()); + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Closing guest session ID=#%RU32 \"%s\" ...\n"), + uID, strNameUtf8.c_str()); + CHECK_ERROR_BREAK(pSession, Close()); + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Guest session successfully closed\n")); + + pSession.setNull(); + } + } + + if (!cSessionsHandled) + { + RTPrintf(GuestCtrl::tr("No guest session(s) found\n")); + hrc = E_ABORT; /* To set exit code accordingly. */ + } + + } while (0); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static DECLCALLBACK(RTEXITCODE) gctlHandleWatch(PGCTLCMDCTX pCtx, int argc, char **argv) +{ + AssertPtrReturn(pCtx, RTEXITCODE_FAILURE); + + /* + * Parse arguments. + */ + static const RTGETOPTDEF s_aOptions[] = + { + GCTLCMD_COMMON_OPTION_DEFS() + { "--timeout", 't', RTGETOPT_REQ_UINT32 } + }; + + uint32_t cMsTimeout = RT_INDEFINITE_WAIT; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(pCtx, ch, &ValueUnion); + + case 't': /* Timeout */ + cMsTimeout = ValueUnion.u32; + break; + + case VINF_GETOPT_NOT_OPTION: + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + /** @todo Specify categories to watch for. */ + + RTEXITCODE rcExit = gctlCtxPostOptionParsingInit(pCtx); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + + HRESULT hrc; + + try + { + ComObjPtr<GuestEventListenerImpl> pGuestListener; + do + { + /* Listener creation. */ + pGuestListener.createObject(); + pGuestListener->init(new GuestEventListener()); + + /* Register for IGuest events. */ + ComPtr<IEventSource> es; + CHECK_ERROR_BREAK(pCtx->pGuest, COMGETTER(EventSource)(es.asOutParam())); + com::SafeArray<VBoxEventType_T> eventTypes; + eventTypes.push_back(VBoxEventType_OnGuestSessionRegistered); + /** @todo Also register for VBoxEventType_OnGuestUserStateChanged on demand? */ + CHECK_ERROR_BREAK(es, RegisterListener(pGuestListener, ComSafeArrayAsInParam(eventTypes), + true /* Active listener */)); + /* Note: All other guest control events have to be registered + * as their corresponding objects appear. */ + + } while (0); + + if (pCtx->cVerbose) + RTPrintf(GuestCtrl::tr("Waiting for events ...\n")); + + RTMSINTERVAL tsStart = RTTimeMilliTS(); + while (RTTimeMilliTS() - tsStart < cMsTimeout) + { + /* Wait for the global signal semaphore getting signalled. */ + int vrc = RTSemEventWait(g_SemEventGuestCtrlCanceled, 100 /* ms */); + if (RT_FAILURE(vrc)) + { + if (vrc != VERR_TIMEOUT) + { + RTPrintf(GuestCtrl::tr("Waiting failed with %Rrc\n"), vrc); + break; + } + } + else + break; + + /* We need to process the event queue, otherwise our registered listeners won't get any events. */ + NativeEventQueue::getMainEventQueue()->processEventQueue(0); + } + + if (!pGuestListener.isNull()) + { + /* Guest callback unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR(pCtx->pGuest, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR(pES, UnregisterListener(pGuestListener)); + pGuestListener.setNull(); + } + } + catch (std::bad_alloc &) + { + hrc = E_OUTOFMEMORY; + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * Access the guest control store. + * + * @returns program exit code. + * @note see the command line API description for parameters + */ +RTEXITCODE handleGuestControl(HandlerArg *pArg) +{ + AssertPtr(pArg); + + /* + * Command definitions. + */ + static const GCTLCMDDEF s_aCmdDefs[] = + { + { "run", gctlHandleRun, HELP_SCOPE_GUESTCONTROL_RUN, 0 }, + { "start", gctlHandleStart, HELP_SCOPE_GUESTCONTROL_START, 0 }, + { "copyfrom", gctlHandleCopyFrom, HELP_SCOPE_GUESTCONTROL_COPYFROM, 0 }, + { "copyto", gctlHandleCopyTo, HELP_SCOPE_GUESTCONTROL_COPYTO, 0 }, + + { "mkdir", gctrlHandleMkDir, HELP_SCOPE_GUESTCONTROL_MKDIR, 0 }, + { "md", gctrlHandleMkDir, HELP_SCOPE_GUESTCONTROL_MKDIR, 0 }, + { "createdirectory", gctrlHandleMkDir, HELP_SCOPE_GUESTCONTROL_MKDIR, 0 }, + { "createdir", gctrlHandleMkDir, HELP_SCOPE_GUESTCONTROL_MKDIR, 0 }, + + { "rmdir", gctlHandleRmDir, HELP_SCOPE_GUESTCONTROL_RMDIR, 0 }, + { "removedir", gctlHandleRmDir, HELP_SCOPE_GUESTCONTROL_RMDIR, 0 }, + { "removedirectory", gctlHandleRmDir, HELP_SCOPE_GUESTCONTROL_RMDIR, 0 }, + + { "rm", gctlHandleRm, HELP_SCOPE_GUESTCONTROL_RM, 0 }, + { "removefile", gctlHandleRm, HELP_SCOPE_GUESTCONTROL_RM, 0 }, + { "erase", gctlHandleRm, HELP_SCOPE_GUESTCONTROL_RM, 0 }, + { "del", gctlHandleRm, HELP_SCOPE_GUESTCONTROL_RM, 0 }, + { "delete", gctlHandleRm, HELP_SCOPE_GUESTCONTROL_RM, 0 }, + + { "mv", gctlHandleMv, HELP_SCOPE_GUESTCONTROL_MV, 0 }, + { "move", gctlHandleMv, HELP_SCOPE_GUESTCONTROL_MV, 0 }, + { "ren", gctlHandleMv, HELP_SCOPE_GUESTCONTROL_MV, 0 }, + { "rename", gctlHandleMv, HELP_SCOPE_GUESTCONTROL_MV, 0 }, + + { "mktemp", gctlHandleMkTemp, HELP_SCOPE_GUESTCONTROL_MKTEMP, 0 }, + { "createtemp", gctlHandleMkTemp, HELP_SCOPE_GUESTCONTROL_MKTEMP, 0 }, + { "createtemporary", gctlHandleMkTemp, HELP_SCOPE_GUESTCONTROL_MKTEMP, 0 }, + + { "stat", gctlHandleStat, HELP_SCOPE_GUESTCONTROL_STAT, 0 }, + + { "closeprocess", gctlHandleCloseProcess, HELP_SCOPE_GUESTCONTROL_CLOSEPROCESS, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER }, + { "closesession", gctlHandleCloseSession, HELP_SCOPE_GUESTCONTROL_CLOSESESSION, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER }, + { "list", gctlHandleList, HELP_SCOPE_GUESTCONTROL_LIST, GCTLCMDCTX_F_SESSION_ANONYMOUS | GCTLCMDCTX_F_NO_SIGNAL_HANDLER }, + { "watch", gctlHandleWatch, HELP_SCOPE_GUESTCONTROL_WATCH, GCTLCMDCTX_F_SESSION_ANONYMOUS }, + + {"updateguestadditions",gctlHandleUpdateAdditions, HELP_SCOPE_GUESTCONTROL_UPDATEGA, GCTLCMDCTX_F_SESSION_ANONYMOUS }, + { "updateadditions", gctlHandleUpdateAdditions, HELP_SCOPE_GUESTCONTROL_UPDATEGA, GCTLCMDCTX_F_SESSION_ANONYMOUS }, + { "updatega", gctlHandleUpdateAdditions, HELP_SCOPE_GUESTCONTROL_UPDATEGA, GCTLCMDCTX_F_SESSION_ANONYMOUS }, + + { "waitrunlevel", gctlHandleWaitRunLevel, HELP_SCOPE_GUESTCONTROL_WAITRUNLEVEL, GCTLCMDCTX_F_SESSION_ANONYMOUS }, + { "waitforrunlevel", gctlHandleWaitRunLevel, HELP_SCOPE_GUESTCONTROL_WAITRUNLEVEL, GCTLCMDCTX_F_SESSION_ANONYMOUS }, + }; + + /* + * VBoxManage guestcontrol [common-options] <VM> [common-options] <sub-command> ... + * + * Parse common options and VM name until we find a sub-command. Allowing + * the user to put the user and password related options before the + * sub-command makes it easier to edit the command line when doing several + * operations with the same guest user account. (Accidentally, it also + * makes the syntax diagram shorter and easier to read.) + */ + GCTLCMDCTX CmdCtx; + RTEXITCODE rcExit = gctrCmdCtxInit(&CmdCtx, pArg); + if (rcExit == RTEXITCODE_SUCCESS) + { + static const RTGETOPTDEF s_CommonOptions[] = { GCTLCMD_COMMON_OPTION_DEFS() }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, pArg->argc, pArg->argv, s_CommonOptions, RT_ELEMENTS(s_CommonOptions), 0, 0 /* No sorting! */); + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (ch) + { + GCTLCMD_COMMON_OPTION_CASES(&CmdCtx, ch, &ValueUnion); + + case VINF_GETOPT_NOT_OPTION: + /* First comes the VM name or UUID. */ + if (!CmdCtx.pszVmNameOrUuid) + CmdCtx.pszVmNameOrUuid = ValueUnion.psz; + /* + * The sub-command is next. Look it up and invoke it. + * Note! Currently no warnings about user/password options (like we'll do later on) + * for GCTLCMDCTX_F_SESSION_ANONYMOUS commands. No reason to be too pedantic. + */ + else + { + const char *pszCmd = ValueUnion.psz; + uint32_t iCmd; + for (iCmd = 0; iCmd < RT_ELEMENTS(s_aCmdDefs); iCmd++) + if (strcmp(s_aCmdDefs[iCmd].pszName, pszCmd) == 0) + { + CmdCtx.pCmdDef = &s_aCmdDefs[iCmd]; + + setCurrentSubcommand(s_aCmdDefs[iCmd].fSubcommandScope); + rcExit = s_aCmdDefs[iCmd].pfnHandler(&CmdCtx, pArg->argc - GetState.iNext + 1, + &pArg->argv[GetState.iNext - 1]); + + gctlCtxTerm(&CmdCtx); + return rcExit; + } + return errorSyntax(GuestCtrl::tr("Unknown sub-command: '%s'"), pszCmd); + } + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + if (CmdCtx.pszVmNameOrUuid) + rcExit = errorSyntax(GuestCtrl::tr("Missing sub-command")); + else + rcExit = errorSyntax(GuestCtrl::tr("Missing VM name and sub-command")); + } + return rcExit; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.h b/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.h new file mode 100644 index 00000000..c98cad06 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.h @@ -0,0 +1,270 @@ +/* $Id: VBoxManageGuestCtrl.h $ */ +/** @file + * VBoxManageGuestCtrl.h - Definitions for guest control. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_VBoxManage_VBoxManageGuestCtrl_h +#define VBOX_INCLUDED_SRC_VBoxManage_VBoxManageGuestCtrl_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/com.h> +#include <VBox/com/listeners.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/semaphore.h> +#include <iprt/time.h> + +#include <map> + +const char *gctlFileStatusToText(FileStatus_T enmStatus); +const char *gctlProcessStatusToText(ProcessStatus_T enmStatus); +const char *gctlGuestSessionStatusToText(GuestSessionStatus_T enmStatus); + +using namespace com; + +class GuestFileEventListener; +typedef ListenerImpl<GuestFileEventListener> GuestFileEventListenerImpl; + +class GuestProcessEventListener; +typedef ListenerImpl<GuestProcessEventListener> GuestProcessEventListenerImpl; + +class GuestSessionEventListener; +typedef ListenerImpl<GuestSessionEventListener> GuestSessionEventListenerImpl; + +class GuestEventListener; +typedef ListenerImpl<GuestEventListener> GuestEventListenerImpl; + +class GuestAdditionsRunlevelListener; +typedef ListenerImpl<GuestAdditionsRunlevelListener> GuestAdditionsRunlevelListenerImpl; + +/** Simple statistics class for binding locally + * held data to a specific guest object. */ +class GuestEventStats +{ + +public: + + GuestEventStats(void) + : uLastUpdatedMS(RTTimeMilliTS()) + { + } + + /** @todo Make this more a class than a structure. */ +public: + + uint64_t uLastUpdatedMS; +}; + +class GuestFileStats : public GuestEventStats +{ + +public: + + GuestFileStats(void) { } + + GuestFileStats(ComObjPtr<GuestFileEventListenerImpl> pListenerImpl) + : mListener(pListenerImpl) + { + } + +public: /** @todo */ + + ComObjPtr<GuestFileEventListenerImpl> mListener; +}; + +class GuestProcStats : public GuestEventStats +{ + +public: + + GuestProcStats(void) { } + + GuestProcStats(ComObjPtr<GuestProcessEventListenerImpl> pListenerImpl) + : mListener(pListenerImpl) + { + } + +public: /** @todo */ + + ComObjPtr<GuestProcessEventListenerImpl> mListener; +}; + +class GuestSessionStats : public GuestEventStats +{ + +public: + + GuestSessionStats(void) { } + + GuestSessionStats(ComObjPtr<GuestSessionEventListenerImpl> pListenerImpl) + : mListener(pListenerImpl) + { + } + +public: /** @todo */ + + ComObjPtr<GuestSessionEventListenerImpl> mListener; +}; + +/** Map containing all watched guest files. */ +typedef std::map< ComPtr<IGuestFile>, GuestFileStats > GuestEventFiles; +/** Map containing all watched guest processes. */ +typedef std::map< ComPtr<IGuestProcess>, GuestProcStats > GuestEventProcs; +/** Map containing all watched guest sessions. */ +typedef std::map< ComPtr<IGuestSession>, GuestSessionStats > GuestEventSessions; + +class GuestListenerBase +{ +public: + + GuestListenerBase(void); + + virtual ~GuestListenerBase(void); + +public: + + HRESULT init(bool fVerbose = false); + +protected: + + /** Verbose flag. */ + bool mfVerbose; +}; + +/** + * Handler for guest process events. + */ +class GuestFileEventListener : public GuestListenerBase +{ +public: + + GuestFileEventListener(void); + + virtual ~GuestFileEventListener(void); + +public: + + void uninit(void); + + STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent); + +protected: + +}; + +/** + * Handler for guest process events. + */ +class GuestProcessEventListener : public GuestListenerBase +{ +public: + + GuestProcessEventListener(void); + + virtual ~GuestProcessEventListener(void); + +public: + + void uninit(void); + + STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent); + +protected: + +}; + +/** + * Handler for guest session events. + */ +class GuestSessionEventListener : public GuestListenerBase +{ +public: + + GuestSessionEventListener(void); + + virtual ~GuestSessionEventListener(void); + +public: + + void uninit(void); + + STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent); + +protected: + + GuestEventFiles mFiles; + GuestEventProcs mProcs; +}; + +/** + * Handler for guest events. + */ +class GuestEventListener : public GuestListenerBase +{ + +public: + + GuestEventListener(void); + + virtual ~GuestEventListener(void); + +public: + + void uninit(void); + + STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent); + +protected: + + GuestEventSessions mSessions; +}; + +/** + * Handler for Guest Additions runlevel change events. + */ +class GuestAdditionsRunlevelListener : public GuestListenerBase +{ + +public: + + GuestAdditionsRunlevelListener(AdditionsRunLevelType_T enmRunLevel); + + virtual ~GuestAdditionsRunlevelListener(void); + +public: + + void uninit(void); + + STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent); + +protected: + + /** The run level target we're waiting for. */ + AdditionsRunLevelType_T mRunLevelTarget; +}; + +#endif /* !VBOX_INCLUDED_SRC_VBoxManage_VBoxManageGuestCtrl_h */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrlListener.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrlListener.cpp new file mode 100644 index 00000000..0fada6d0 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrlListener.cpp @@ -0,0 +1,578 @@ +/* $Id: VBoxManageGuestCtrlListener.cpp $ */ +/** @file + * VBoxManage - Guest control listener implementations. + */ + +/* + * Copyright (C) 2013-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "VBoxManage.h" +#include "VBoxManageGuestCtrl.h" + +#include <VBox/com/com.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> + +#include <iprt/semaphore.h> +#include <iprt/time.h> + +#include <map> +#include <vector> + +DECLARE_TRANSLATION_CONTEXT(GuestCtrlLsnr); + + +/** Event semaphore we're using for notification. */ +extern RTSEMEVENT g_SemEventGuestCtrlCanceled; + + +/* + * GuestListenerBase + * GuestListenerBase + * GuestListenerBase + */ + +GuestListenerBase::GuestListenerBase(void) + : mfVerbose(false) +{ +} + +GuestListenerBase::~GuestListenerBase(void) +{ +} + +HRESULT GuestListenerBase::init(bool fVerbose) +{ + mfVerbose = fVerbose; + return S_OK; +} + + + +/* + * GuestFileEventListener + * GuestFileEventListener + * GuestFileEventListener + */ + +GuestFileEventListener::GuestFileEventListener(void) +{ +} + +GuestFileEventListener::~GuestFileEventListener(void) +{ +} + +void GuestFileEventListener::uninit(void) +{ + +} + +STDMETHODIMP GuestFileEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent) +{ + switch (aType) + { + case VBoxEventType_OnGuestFileStateChanged: + { + HRESULT hrc; + do + { + ComPtr<IGuestFileStateChangedEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + + ComPtr<IGuestFile> pProcess; + CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pProcess.asOutParam())); + AssertBreak(!pProcess.isNull()); + FileStatus_T fileSts; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&fileSts)); + Bstr strPath; + CHECK_ERROR_BREAK(pProcess, COMGETTER(Filename)(strPath.asOutParam())); + ULONG uID; + CHECK_ERROR_BREAK(pProcess, COMGETTER(Id)(&uID)); + + RTPrintf(GuestCtrlLsnr::tr("File ID=%RU32 \"%s\" changed status to [%s]\n"), + uID, Utf8Str(strPath).c_str(), gctlFileStatusToText(fileSts)); + + } while (0); + break; + } + + default: + AssertFailed(); + } + + return S_OK; +} + + +/* + * GuestProcessEventListener + * GuestProcessEventListener + * GuestProcessEventListener + */ + +GuestProcessEventListener::GuestProcessEventListener(void) +{ +} + +GuestProcessEventListener::~GuestProcessEventListener(void) +{ +} + +void GuestProcessEventListener::uninit(void) +{ + +} + +STDMETHODIMP GuestProcessEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent) +{ + switch (aType) + { + case VBoxEventType_OnGuestProcessStateChanged: + { + HRESULT hrc; + do + { + ComPtr<IGuestProcessStateChangedEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + + ComPtr<IGuestProcess> pProcess; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam())); + AssertBreak(!pProcess.isNull()); + ProcessStatus_T procSts; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Status)(&procSts)); + Bstr strPath; + CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam())); + ULONG uPID; + CHECK_ERROR_BREAK(pProcess, COMGETTER(PID)(&uPID)); + + RTPrintf(GuestCtrlLsnr::tr("Process PID=%RU32 \"%s\" changed status to [%s]\n"), + uPID, Utf8Str(strPath).c_str(), gctlProcessStatusToText(procSts)); + + } while (0); + break; + } + + default: + AssertFailed(); + } + + return S_OK; +} + + +/* + * GuestSessionEventListener + * GuestSessionEventListener + * GuestSessionEventListener + */ + +GuestSessionEventListener::GuestSessionEventListener(void) +{ +} + +GuestSessionEventListener::~GuestSessionEventListener(void) +{ +} + +void GuestSessionEventListener::uninit(void) +{ + GuestEventProcs::iterator itProc = mProcs.begin(); + while (itProc != mProcs.end()) + { + if (!itProc->first.isNull()) + { + HRESULT hrc; + do + { + /* Listener unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR_BREAK(itProc->first, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR_BREAK(pES, UnregisterListener(itProc->second.mListener)); + } while (0); + } + + ++itProc; + } + mProcs.clear(); + + GuestEventFiles::iterator itFile = mFiles.begin(); + while (itFile != mFiles.end()) + { + if (!itFile->first.isNull()) + { + HRESULT hrc; + do + { + /* Listener unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR_BREAK(itFile->first, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR_BREAK(pES, UnregisterListener(itFile->second.mListener)); + } while (0); + } + + ++itFile; + } + mFiles.clear(); +} + +STDMETHODIMP GuestSessionEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent) +{ + switch (aType) + { + case VBoxEventType_OnGuestFileRegistered: + { + HRESULT hrc; + do + { + ComPtr<IGuestFileRegisteredEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + + ComPtr<IGuestFile> pFile; + CHECK_ERROR_BREAK(pEvent, COMGETTER(File)(pFile.asOutParam())); + AssertBreak(!pFile.isNull()); + BOOL fRegistered; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered)); + Bstr strPath; + CHECK_ERROR_BREAK(pFile, COMGETTER(Filename)(strPath.asOutParam())); + + RTPrintf(GuestCtrlLsnr::tr("File \"%s\" %s\n"), + Utf8Str(strPath).c_str(), + fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered")); + if (fRegistered) + { + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Registering ...\n")); + + /* Register for IGuestFile events. */ + ComObjPtr<GuestFileEventListenerImpl> pListener; + pListener.createObject(); + CHECK_ERROR_BREAK(pListener, init(new GuestFileEventListener())); + + ComPtr<IEventSource> es; + CHECK_ERROR_BREAK(pFile, COMGETTER(EventSource)(es.asOutParam())); + com::SafeArray<VBoxEventType_T> eventTypes; + eventTypes.push_back(VBoxEventType_OnGuestFileStateChanged); + CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), + true /* Active listener */)); + + GuestFileStats fileStats(pListener); + mFiles[pFile] = fileStats; + } + else + { + GuestEventFiles::iterator itFile = mFiles.find(pFile); + if (itFile != mFiles.end()) + { + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Unregistering file ...\n")); + + if (!itFile->first.isNull()) + { + /* Listener unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR(itFile->first, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR(pES, UnregisterListener(itFile->second.mListener)); + } + + mFiles.erase(itFile); + } + } + + } while (0); + break; + } + + case VBoxEventType_OnGuestProcessRegistered: + { + HRESULT hrc; + do + { + ComPtr<IGuestProcessRegisteredEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + + ComPtr<IGuestProcess> pProcess; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Process)(pProcess.asOutParam())); + AssertBreak(!pProcess.isNull()); + BOOL fRegistered; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered)); + Bstr strPath; + CHECK_ERROR_BREAK(pProcess, COMGETTER(ExecutablePath)(strPath.asOutParam())); + + RTPrintf(GuestCtrlLsnr::tr("Process \"%s\" %s\n"), + Utf8Str(strPath).c_str(), + fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered")); + if (fRegistered) + { + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Registering ...\n")); + + /* Register for IGuestProcess events. */ + ComObjPtr<GuestProcessEventListenerImpl> pListener; + pListener.createObject(); + CHECK_ERROR_BREAK(pListener, init(new GuestProcessEventListener())); + + ComPtr<IEventSource> es; + CHECK_ERROR_BREAK(pProcess, COMGETTER(EventSource)(es.asOutParam())); + com::SafeArray<VBoxEventType_T> eventTypes; + eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged); + CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), + true /* Active listener */)); + + GuestProcStats procStats(pListener); + mProcs[pProcess] = procStats; + } + else + { + GuestEventProcs::iterator itProc = mProcs.find(pProcess); + if (itProc != mProcs.end()) + { + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Unregistering process ...\n")); + + if (!itProc->first.isNull()) + { + /* Listener unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR(itProc->first, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR(pES, UnregisterListener(itProc->second.mListener)); + } + + mProcs.erase(itProc); + } + } + + } while (0); + break; + } + + case VBoxEventType_OnGuestSessionStateChanged: + { + HRESULT hrc; + do + { + ComPtr<IGuestSessionStateChangedEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + ComPtr<IGuestSession> pSession; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam())); + AssertBreak(!pSession.isNull()); + + GuestSessionStatus_T sessSts; + CHECK_ERROR_BREAK(pSession, COMGETTER(Status)(&sessSts)); + ULONG uID; + CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID)); + Bstr strName; + CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam())); + + RTPrintf(GuestCtrlLsnr::tr("Session ID=%RU32 \"%s\" changed status to [%s]\n"), + uID, Utf8Str(strName).c_str(), gctlGuestSessionStatusToText(sessSts)); + + } while (0); + break; + } + + default: + AssertFailed(); + } + + return S_OK; +} + + +/* + * GuestEventListener + * GuestEventListener + * GuestEventListener + */ + +GuestEventListener::GuestEventListener(void) +{ +} + +GuestEventListener::~GuestEventListener(void) +{ +} + +void GuestEventListener::uninit(void) +{ + GuestEventSessions::iterator itSession = mSessions.begin(); + while (itSession != mSessions.end()) + { + if (!itSession->first.isNull()) + { + HRESULT hrc; + do + { + /* Listener unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener)); + + } while (0); + } + + ++itSession; + } + mSessions.clear(); +} + +STDMETHODIMP GuestEventListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent) +{ + switch (aType) + { + case VBoxEventType_OnGuestSessionRegistered: + { + HRESULT hrc; + do + { + ComPtr<IGuestSessionRegisteredEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + + ComPtr<IGuestSession> pSession; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Session)(pSession.asOutParam())); + AssertBreak(!pSession.isNull()); + BOOL fRegistered; + CHECK_ERROR_BREAK(pEvent, COMGETTER(Registered)(&fRegistered)); + Bstr strName; + CHECK_ERROR_BREAK(pSession, COMGETTER(Name)(strName.asOutParam())); + ULONG uID; + CHECK_ERROR_BREAK(pSession, COMGETTER(Id)(&uID)); + + RTPrintf(GuestCtrlLsnr::tr("Session ID=%RU32 \"%s\" %s\n"), + uID, Utf8Str(strName).c_str(), + fRegistered ? GuestCtrlLsnr::tr("registered") : GuestCtrlLsnr::tr("unregistered")); + if (fRegistered) + { + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Registering ...\n")); + + /* Register for IGuestSession events. */ + ComObjPtr<GuestSessionEventListenerImpl> pListener; + pListener.createObject(); + CHECK_ERROR_BREAK(pListener, init(new GuestSessionEventListener())); + + ComPtr<IEventSource> es; + CHECK_ERROR_BREAK(pSession, COMGETTER(EventSource)(es.asOutParam())); + com::SafeArray<VBoxEventType_T> eventTypes; + eventTypes.push_back(VBoxEventType_OnGuestFileRegistered); + eventTypes.push_back(VBoxEventType_OnGuestProcessRegistered); + eventTypes.push_back(VBoxEventType_OnGuestSessionStateChanged); + CHECK_ERROR_BREAK(es, RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), + true /* Active listener */)); + + GuestSessionStats sessionStats(pListener); + mSessions[pSession] = sessionStats; + } + else + { + GuestEventSessions::iterator itSession = mSessions.find(pSession); + if (itSession != mSessions.end()) + { + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Unregistering ...\n")); + + if (!itSession->first.isNull()) + { + /* Listener unregistration. */ + ComPtr<IEventSource> pES; + CHECK_ERROR_BREAK(itSession->first, COMGETTER(EventSource)(pES.asOutParam())); + if (!pES.isNull()) + CHECK_ERROR_BREAK(pES, UnregisterListener(itSession->second.mListener)); + } + + mSessions.erase(itSession); + } + } + + } while (0); + break; + } + + default: + AssertFailed(); + } + + return S_OK; +} + +/* + * GuestAdditionsRunlevelListener + * GuestAdditionsRunlevelListener + * GuestAdditionsRunlevelListener + */ + +GuestAdditionsRunlevelListener::GuestAdditionsRunlevelListener(AdditionsRunLevelType_T enmRunLevel) + : mRunLevelTarget(enmRunLevel) +{ +} + +GuestAdditionsRunlevelListener::~GuestAdditionsRunlevelListener(void) +{ +} + +void GuestAdditionsRunlevelListener::uninit(void) +{ +} + +STDMETHODIMP GuestAdditionsRunlevelListener::HandleEvent(VBoxEventType_T aType, IEvent *aEvent) +{ + Assert(mRunLevelTarget != AdditionsRunLevelType_None); + + HRESULT hrc; + + switch (aType) + { + case VBoxEventType_OnGuestAdditionsStatusChanged: + { + ComPtr<IGuestAdditionsStatusChangedEvent> pEvent = aEvent; + Assert(!pEvent.isNull()); + + AdditionsRunLevelType_T RunLevelCur = AdditionsRunLevelType_None; + CHECK_ERROR_BREAK(pEvent, COMGETTER(RunLevel)(&RunLevelCur)); + + if (mfVerbose) + RTPrintf(GuestCtrlLsnr::tr("Reached run level %RU32\n"), RunLevelCur); + + if (RunLevelCur == mRunLevelTarget) + { + int vrc = RTSemEventSignal(g_SemEventGuestCtrlCanceled); + AssertRC(vrc); + } + + break; + } + + default: + AssertFailed(); + } + + return S_OK; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp new file mode 100644 index 00000000..bed0edea --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp @@ -0,0 +1,601 @@ +/* $Id: VBoxManageGuestProp.cpp $ */ +/** @file + * VBoxManage - Implementation of guestproperty command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include "VBoxManage.h" + +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <VBox/log.h> +#include <iprt/asm.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/time.h> +#include <iprt/thread.h> + +#ifdef USE_XPCOM_QUEUE +# include <sys/select.h> +# include <errno.h> +#endif + +#ifdef RT_OS_DARWIN +# include <CoreFoundation/CFRunLoop.h> +#endif + +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(GuestProp); + + +static RTEXITCODE handleGetGuestProperty(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + setCurrentSubcommand(HELP_SCOPE_GUESTPROPERTY_GET); + + bool verbose = false; + if ( a->argc == 3 + && ( !strcmp(a->argv[2], "--verbose") + || !strcmp(a->argv[2], "-verbose"))) + verbose = true; + else if (a->argc != 2) + return errorSyntax(GuestProp::tr("Incorrect parameters")); + + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + /* open a session for the VM - new or existing */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + + Bstr value; + LONG64 i64Timestamp; + Bstr flags; + CHECK_ERROR(machine, GetGuestProperty(Bstr(a->argv[1]).raw(), + value.asOutParam(), + &i64Timestamp, flags.asOutParam())); + if (value.isEmpty()) + RTPrintf(GuestProp::tr("No value set!\n")); + else + RTPrintf(GuestProp::tr("Value: %ls\n"), value.raw()); + if (!value.isEmpty() && verbose) + { + RTPrintf(GuestProp::tr("Timestamp: %lld\n"), i64Timestamp); + RTPrintf(GuestProp::tr("Flags: %ls\n"), flags.raw()); + } + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE handleSetGuestProperty(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + setCurrentSubcommand(HELP_SCOPE_GUESTPROPERTY_SET); + + /* + * Check the syntax. We can deduce the correct syntax from the number of + * arguments. + */ + bool usageOK = true; + const char *pszName = NULL; + const char *pszValue = NULL; + const char *pszFlags = NULL; + if (a->argc == 3) + pszValue = a->argv[2]; + else if (a->argc == 4) + usageOK = false; + else if (a->argc == 5) + { + pszValue = a->argv[2]; + if ( strcmp(a->argv[3], "--flags") + && strcmp(a->argv[3], "-flags")) + usageOK = false; + pszFlags = a->argv[4]; + } + else if (a->argc != 2) + usageOK = false; + if (!usageOK) + return errorSyntax(GuestProp::tr("Incorrect parameters")); + /* This is always needed. */ + pszName = a->argv[1]; + + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + /* open a session for the VM - new or existing */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + + if (!pszFlags) + CHECK_ERROR(machine, SetGuestPropertyValue(Bstr(pszName).raw(), + Bstr(pszValue).raw())); + else + CHECK_ERROR(machine, SetGuestProperty(Bstr(pszName).raw(), + Bstr(pszValue).raw(), + Bstr(pszFlags).raw())); + + if (SUCCEEDED(hrc)) + CHECK_ERROR(machine, SaveSettings()); + + a->session->UnlockMachine(); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE handleDeleteGuestProperty(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + setCurrentSubcommand(HELP_SCOPE_GUESTPROPERTY_UNSET); + + /* + * Check the syntax. We can deduce the correct syntax from the number of + * arguments. + */ + bool usageOK = true; + const char *pszName = NULL; + if (a->argc != 2) + usageOK = false; + if (!usageOK) + return errorSyntax(GuestProp::tr("Incorrect parameters")); + /* This is always needed. */ + pszName = a->argv[1]; + + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + /* open a session for the VM - new or existing */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + + CHECK_ERROR(machine, DeleteGuestProperty(Bstr(pszName).raw())); + + if (SUCCEEDED(hrc)) + CHECK_ERROR(machine, SaveSettings()); + + a->session->UnlockMachine(); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * Enumerates the properties in the guest property store. + * + * @returns 0 on success, 1 on failure + * @note see the command line API description for parameters + */ +static RTEXITCODE handleEnumGuestProperty(HandlerArg *a) +{ + setCurrentSubcommand(HELP_SCOPE_GUESTPROPERTY_ENUMERATE); + + /* + * Parse arguments. + * + * The old syntax was a little boinkers. The --patterns argument just + * indicates that the rest of the arguments are options. Sort of like '--'. + * This has been normalized a little now, by accepting patterns w/o a + * preceding --pattern argument via the VINF_GETOPT_NOT_OPTION. + * Though, the first non-option is always the VM name. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--old-format", 'o', RTGETOPT_REQ_NOTHING }, + { "--sort", 's', RTGETOPT_REQ_NOTHING }, + { "--unsort", 'u', RTGETOPT_REQ_NOTHING }, + { "--timestamp", 't', RTGETOPT_REQ_NOTHING }, + { "--ts", 't', RTGETOPT_REQ_NOTHING }, + { "--no-timestamp", 'T', RTGETOPT_REQ_NOTHING }, + { "--abs", 'a', RTGETOPT_REQ_NOTHING }, + { "--absolute", 'a', RTGETOPT_REQ_NOTHING }, + { "--rel", 'r', RTGETOPT_REQ_NOTHING }, + { "--relative", 'r', RTGETOPT_REQ_NOTHING }, + { "--no-ts", 'T', RTGETOPT_REQ_NOTHING }, + { "--flags", 'f', RTGETOPT_REQ_NOTHING }, + { "--no-flags", 'F', RTGETOPT_REQ_NOTHING }, + /* unnecessary legacy: */ + { "--patterns", 'p', RTGETOPT_REQ_STRING }, + { "-patterns", 'p', RTGETOPT_REQ_STRING }, + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + + const char *pszVmNameOrUuid = NULL; + Utf8Str strPatterns; + bool fSort = true; + bool fNewStyle = true; + bool fTimestamp = true; + bool fAbsTime = true; + bool fFlags = true; + + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + /* For options that require an argument, ValueUnion has received the value. */ + switch (ch) + { + case VINF_GETOPT_NOT_OPTION: + /* The first one is the VM name. */ + if (!pszVmNameOrUuid) + { + pszVmNameOrUuid = ValueUnion.psz; + break; + } + /* Everything else would be patterns by the new syntax. */ + RT_FALL_THROUGH(); + case 'p': + if (strPatterns.isNotEmpty()) + if (RT_FAILURE(strPatterns.appendNoThrow(','))) + return RTMsgErrorExitFailure("out of memory!"); + if (RT_FAILURE(strPatterns.appendNoThrow(ValueUnion.psz))) + return RTMsgErrorExitFailure("out of memory!"); + break; + + case 'o': + fNewStyle = false; + break; + + case 's': + fSort = true; + break; + case 'u': + fSort = false; + break; + + case 't': + fTimestamp = true; + break; + case 'T': + fTimestamp = false; + break; + + case 'a': + fAbsTime = true; + break; + case 'r': + fAbsTime = false; + break; + + case 'f': + fFlags = true; + break; + case 'F': + fFlags = false; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + /* Only the VM name is required. */ + if (!pszVmNameOrUuid) + return errorSyntax(GuestProp::tr("No VM name or UUID was specified")); + + /* + * Make the actual call to Main. + */ + ComPtr<IMachine> machine; + CHECK_ERROR2I_RET(a->virtualBox, FindMachine(Bstr(pszVmNameOrUuid).raw(), machine.asOutParam()), RTEXITCODE_FAILURE); + + /* open a session for the VM - new or existing */ + CHECK_ERROR2I_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + + com::SafeArray<BSTR> names; + com::SafeArray<BSTR> values; + com::SafeArray<LONG64> timestamps; + com::SafeArray<BSTR> flags; + CHECK_ERROR2I_RET(machine, EnumerateGuestProperties(Bstr(strPatterns).raw(), + ComSafeArrayAsOutParam(names), + ComSafeArrayAsOutParam(values), + ComSafeArrayAsOutParam(timestamps), + ComSafeArrayAsOutParam(flags)), + RTEXITCODE_FAILURE); + + size_t const cEntries = names.size(); + if (cEntries == 0) + RTPrintf(GuestProp::tr("No properties found.\n")); + else + { + /* Whether we sort it or not, we work it via a indirect index: */ + size_t *paidxSorted = (size_t *)RTMemAlloc(sizeof(paidxSorted[0]) * cEntries); + if (!paidxSorted) + return RTMsgErrorExitFailure("out of memory!"); + for (size_t i = 0; i < cEntries; i++) + paidxSorted[i] = i; + + /* Do the sorting: */ + if (fSort && cEntries > 1) + for (size_t i = 0; i < cEntries - 1; i++) + for (size_t j = 0; j < cEntries - i - 1; j++) + if (RTUtf16Cmp(names[paidxSorted[j]], names[paidxSorted[j + 1]]) > 0) + { + size_t iTmp = paidxSorted[j]; + paidxSorted[j] = paidxSorted[j + 1]; + paidxSorted[j + 1] = iTmp; + } + + if (fNewStyle) + { + /* figure the width of the main columns: */ + size_t cwcMaxName = 1; + size_t cwcMaxValue = 1; + for (size_t i = 0; i < cEntries; ++i) + { + size_t cwcName = RTUtf16Len(names[i]); + cwcMaxName = RT_MAX(cwcMaxName, cwcName); + size_t cwcValue = RTUtf16Len(values[i]); + cwcMaxValue = RT_MAX(cwcMaxValue, cwcValue); + } + cwcMaxName = RT_MIN(cwcMaxName, 48); + cwcMaxValue = RT_MIN(cwcMaxValue, 28); + + /* Get the current time for relative time formatting: */ + RTTIMESPEC Now; + RTTimeNow(&Now); + + /* Print the table: */ + for (size_t iSorted = 0; iSorted < cEntries; ++iSorted) + { + size_t const i = paidxSorted[iSorted]; + char szTime[80]; + if (fTimestamp) + { + RTTIMESPEC TimestampTS; + RTTimeSpecSetNano(&TimestampTS, timestamps[i]); + if (fAbsTime) + { + RTTIME Timestamp; + RTTimeToStringEx(RTTimeExplode(&Timestamp, &TimestampTS), &szTime[2], sizeof(szTime) - 2, 3); + } + else + { + RTTIMESPEC DurationTS = Now; + RTTimeFormatDurationEx(&szTime[2], sizeof(szTime) - 2, RTTimeSpecSub(&DurationTS, &TimestampTS), 3); + } + szTime[0] = '@'; + szTime[1] = ' '; + } + else + szTime[0] = '\0'; + + static RTUTF16 s_wszEmpty[] = { 0 }; + PCRTUTF16 const pwszFlags = fFlags ? flags[i] : s_wszEmpty; + + int cchOut = RTPrintf("%-*ls = '%ls'", cwcMaxName, names[i], values[i]); + if (fTimestamp || *pwszFlags) + { + size_t const cwcWidth = cwcMaxName + cwcMaxValue + 6; + size_t const cwcValPadding = (unsigned)cchOut < cwcWidth ? cwcWidth - (unsigned)cchOut : 1; + RTPrintf("%*s%s%s%ls\n", cwcValPadding, "", szTime, *pwszFlags ? " " : "", pwszFlags); + } + else + RTPrintf("\n"); + } + } + else + for (size_t iSorted = 0; iSorted < cEntries; ++iSorted) + { + size_t const i = paidxSorted[iSorted]; + RTPrintf(GuestProp::tr("Name: %ls, value: %ls, timestamp: %lld, flags: %ls\n"), + names[i], values[i], timestamps[i], flags[i]); + } + RTMemFree(paidxSorted); + } + + return RTEXITCODE_SUCCESS; +} + +/** + * Enumerates the properties in the guest property store. + * + * @returns 0 on success, 1 on failure + * @note see the command line API description for parameters + */ +static RTEXITCODE handleWaitGuestProperty(HandlerArg *a) +{ + setCurrentSubcommand(HELP_SCOPE_GUESTPROPERTY_WAIT); + + /* + * Handle arguments + */ + bool fFailOnTimeout = false; + const char *pszPatterns = NULL; + uint32_t cMsTimeout = RT_INDEFINITE_WAIT; + bool usageOK = true; + if (a->argc < 2) + usageOK = false; + else + pszPatterns = a->argv[1]; + ComPtr<IMachine> machine; + HRESULT hrc; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (!machine) + usageOK = false; + for (int i = 2; usageOK && i < a->argc; ++i) + { + if ( !strcmp(a->argv[i], "--timeout") + || !strcmp(a->argv[i], "-timeout")) + { + if ( i + 1 >= a->argc + || RTStrToUInt32Full(a->argv[i + 1], 10, &cMsTimeout) != VINF_SUCCESS) + usageOK = false; + else + ++i; + } + else if (!strcmp(a->argv[i], "--fail-on-timeout")) + fFailOnTimeout = true; + else + usageOK = false; + } + if (!usageOK) + return errorSyntax(GuestProp::tr("Incorrect parameters")); + + /* + * Set up the event listener and wait until found match or timeout. + */ + Bstr aMachStrGuid; + machine->COMGETTER(Id)(aMachStrGuid.asOutParam()); + Guid aMachGuid(aMachStrGuid); + ComPtr<IEventSource> es; + CHECK_ERROR(a->virtualBox, COMGETTER(EventSource)(es.asOutParam())); + ComPtr<IEventListener> listener; + CHECK_ERROR(es, CreateListener(listener.asOutParam())); + com::SafeArray <VBoxEventType_T> eventTypes(1); + eventTypes.push_back(VBoxEventType_OnGuestPropertyChanged); + CHECK_ERROR(es, RegisterListener(listener, ComSafeArrayAsInParam(eventTypes), false)); + + uint64_t u64Started = RTTimeMilliTS(); + bool fSignalled = false; + do + { + unsigned cMsWait; + if (cMsTimeout == RT_INDEFINITE_WAIT) + cMsWait = 1000; + else + { + uint64_t cMsElapsed = RTTimeMilliTS() - u64Started; + if (cMsElapsed >= cMsTimeout) + break; /* timed out */ + cMsWait = RT_MIN(1000, cMsTimeout - (uint32_t)cMsElapsed); + } + + ComPtr<IEvent> ev; + hrc = es->GetEvent(listener, cMsWait, ev.asOutParam()); + if (ev) /** @todo r=andy Why not using SUCCEEDED(hrc) here? */ + { + VBoxEventType_T aType; + hrc = ev->COMGETTER(Type)(&aType); + switch (aType) + { + case VBoxEventType_OnGuestPropertyChanged: + { + ComPtr<IGuestPropertyChangedEvent> gpcev = ev; + Assert(gpcev); + Bstr aNextStrGuid; + gpcev->COMGETTER(MachineId)(aNextStrGuid.asOutParam()); + if (aMachGuid != Guid(aNextStrGuid)) + continue; + Bstr aNextName; + gpcev->COMGETTER(Name)(aNextName.asOutParam()); + if (RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX, + Utf8Str(aNextName).c_str(), RTSTR_MAX, NULL)) + { + Bstr aNextValue, aNextFlags; + BOOL aNextWasDeleted; + gpcev->COMGETTER(Value)(aNextValue.asOutParam()); + gpcev->COMGETTER(Flags)(aNextFlags.asOutParam()); + gpcev->COMGETTER(FWasDeleted)(&aNextWasDeleted); + if (aNextWasDeleted) + RTPrintf(GuestProp::tr("Property %ls was deleted\n"), aNextName.raw()); + else + RTPrintf(GuestProp::tr("Name: %ls, value: %ls, flags: %ls\n"), + aNextName.raw(), aNextValue.raw(), aNextFlags.raw()); + fSignalled = true; + } + break; + } + default: + AssertFailed(); + } + } + } while (!fSignalled); + + es->UnregisterListener(listener); + + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + if (!fSignalled) + { + RTMsgError(GuestProp::tr("Time out or interruption while waiting for a notification.")); + if (fFailOnTimeout) + /* Hysterical rasins: We always returned 2 here, which now translates to syntax error... Which is bad. */ + rcExit = RTEXITCODE_SYNTAX; + } + return rcExit; +} + +/** + * Access the guest property store. + * + * @returns 0 on success, 1 on failure + * @note see the command line API description for parameters + */ +RTEXITCODE handleGuestProperty(HandlerArg *a) +{ + if (a->argc == 0) + return errorNoSubcommand(); + + /** @todo This command does not follow the syntax where the <uuid|vmname> + * comes between the command and subcommand. The commands controlvm, + * snapshot and debugvm puts it between. + */ + + const char * const pszSubCmd = a->argv[0]; + a->argc -= 1; + a->argv += 1; + + /* switch (cmd) */ + if (strcmp(pszSubCmd, "get") == 0) + return handleGetGuestProperty(a); + if (strcmp(pszSubCmd, "set") == 0) + return handleSetGuestProperty(a); + if (strcmp(pszSubCmd, "delete") == 0 || strcmp(pszSubCmd, "unset") == 0) + return handleDeleteGuestProperty(a); + if (strcmp(pszSubCmd, "enumerate") == 0 || strcmp(pszSubCmd, "enum") == 0) + return handleEnumGuestProperty(a); + if (strcmp(pszSubCmd, "wait") == 0) + return handleWaitGuestProperty(a); + + /* default: */ + return errorUnknownSubcommand(pszSubCmd); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp new file mode 100644 index 00000000..0b6f39b1 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp @@ -0,0 +1,513 @@ +/* $Id: VBoxManageHelp.cpp $ */ +/** @file + * VBoxManage - help and other message output. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/version.h> + +#include <iprt/asm.h> +#include <iprt/buildconfig.h> +#include <iprt/ctype.h> +#include <iprt/assert.h> +#include <iprt/env.h> +#include <iprt/err.h> +#include <iprt/getopt.h> +#include <iprt/stream.h> +#include <iprt/message.h> +#include <iprt/uni.h> + +#include "VBoxManage.h" + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/** If the usage is the given number of length long or longer, the error is + * repeated so the user can actually see it. */ +#define ERROR_REPEAT_AFTER_USAGE_LENGTH 16 + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +DECLARE_TRANSLATION_CONTEXT(Help); + +static enum HELP_CMD_VBOXMANAGE g_enmCurCommand = HELP_CMD_COMMON; +/** The scope mask for the current subcommand. */ +static uint64_t g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL; + +/** + * Sets the current command. + * + * This affects future calls to error and help functions. + * + * @param enmCommand The command. + */ +void setCurrentCommand(enum HELP_CMD_VBOXMANAGE enmCommand) +{ + Assert(g_enmCurCommand == HELP_CMD_COMMON); + g_enmCurCommand = enmCommand; + g_fCurSubcommandScope = RTMSGREFENTRYSTR_SCOPE_GLOBAL; +} + + +/** + * Sets the current subcommand. + * + * This affects future calls to error and help functions. + * + * @param fSubcommandScope The subcommand scope. + */ +void setCurrentSubcommand(uint64_t fSubcommandScope) +{ + g_fCurSubcommandScope = fSubcommandScope; +} + + +/** + * Takes first char and make it uppercase. + * + * @returns pointer to string starting from next char. + * @param pszSrc Source string. + * @param pszDst Pointer to buffer to place first char uppercase. + */ +static const char *captialize(const char *pszSrc, char *pszDst) +{ + *RTStrPutCp(pszDst, RTUniCpToUpper(RTStrGetCp(pszSrc))) = '\0'; + return RTStrNextCp(pszSrc); +} + + +/** + * Prints brief help for a command or subcommand. + * + * @returns Number of lines written. + * @param enmCommand The command. + * @param fSubcommandScope The subcommand scope, REFENTRYSTR_SCOPE_GLOBAL + * for all. + * @param pStrm The output stream. + */ +static uint32_t printBriefCommandOrSubcommandHelp(enum HELP_CMD_VBOXMANAGE enmCommand, uint64_t fSubcommandScope, PRTSTREAM pStrm) +{ + /* + * Try to find translated, falling back untranslated. + */ + uint32_t cLinesWritten = 0; + uint32_t cPendingBlankLines = 0; + uint32_t cFound = 0; + PCHELP_LANG_ENTRY_T const apHelpLangEntries[] = + { + ASMAtomicUoReadPtrT(&g_pHelpLangEntry, PCHELP_LANG_ENTRY_T), +#ifdef VBOX_WITH_VBOXMANAGE_NLS + &g_aHelpLangEntries[0] +#endif + }; + for (uint32_t k = 0; k < RT_ELEMENTS(apHelpLangEntries) && cFound == 0; k++) + { + /* skip if english is used */ + if (k > 0 && apHelpLangEntries[k] == apHelpLangEntries[0]) + break; + uint32_t const cHelpEntries = *apHelpLangEntries[k]->pcHelpEntries; + for (uint32_t i = 0; i < cHelpEntries; i++) + { + PCRTMSGREFENTRY pHelp = apHelpLangEntries[k]->papHelpEntries[i]; + if ( pHelp->idInternal == (int64_t)enmCommand + || enmCommand == HELP_CMD_COMMON) + { + cFound++; + if (cFound == 1) + { + if (fSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL) + { + char szFirstChar[8]; + RTStrmPrintf(pStrm, Help::tr("Usage - %s%s:\n"), szFirstChar, captialize(pHelp->pszBrief, szFirstChar)); + } + else + RTStrmPrintf(pStrm, Help::tr("Usage:\n")); + } + RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Synopsis, fSubcommandScope, &cPendingBlankLines, &cLinesWritten); + if (!cPendingBlankLines) + cPendingBlankLines = 1; + } + } + } + Assert(cFound > 0); + return cLinesWritten; +} + + +/** + * Prints the brief usage information for the current (sub)command. + * + * @param pStrm The output stream. + */ +void printUsage(PRTSTREAM pStrm) +{ + printBriefCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, pStrm); +} + + +/** + * Prints full help for a command or subcommand. + * + * @param enmCommand The command. + * @param fSubcommandScope The subcommand scope, REFENTRYSTR_SCOPE_GLOBAL + * for all. + * @param pStrm The output stream. + */ +static void printFullCommandOrSubcommandHelp(enum HELP_CMD_VBOXMANAGE enmCommand, uint64_t fSubcommandScope, PRTSTREAM pStrm) +{ + /* Try to find translated, then untranslated */ + uint32_t cPendingBlankLines = 0; + uint32_t cFound = 0; + PCHELP_LANG_ENTRY_T const apHelpLangEntries[] = + { + ASMAtomicUoReadPtrT(&g_pHelpLangEntry, PCHELP_LANG_ENTRY_T), +#ifdef VBOX_WITH_VBOXMANAGE_NLS + &g_aHelpLangEntries[0] +#endif + }; + for (uint32_t k = 0; k < RT_ELEMENTS(apHelpLangEntries) && cFound == 0; k++) + { + /* skip if english is used */ + if (k > 0 && apHelpLangEntries[k] == apHelpLangEntries[0]) + break; + uint32_t const cHelpEntries = *apHelpLangEntries[k]->pcHelpEntries; + for (uint32_t i = 0; i < cHelpEntries; i++) + { + PCRTMSGREFENTRY pHelp = apHelpLangEntries[k]->papHelpEntries[i]; + + if ( pHelp->idInternal == (int64_t)enmCommand + || enmCommand == HELP_CMD_COMMON) + { + cFound++; + RTMsgRefEntryPrintStringTable(pStrm, &pHelp->Help, fSubcommandScope, &cPendingBlankLines, NULL /*pcLinesWritten*/); + if (cPendingBlankLines < 2) + cPendingBlankLines = 2; + } + } + } + Assert(cFound > 0); +} + + +/** + * Prints the full help for the current (sub)command. + * + * @param pStrm The output stream. + */ +void printHelp(PRTSTREAM pStrm) +{ + printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, pStrm); +} + + +/** + * Display no subcommand error message and current command usage. + * + * @returns RTEXITCODE_SYNTAX. + */ +RTEXITCODE errorNoSubcommand(void) +{ + Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); + Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL); + + return errorSyntax(Help::tr("No subcommand specified")); +} + + +/** + * Display unknown subcommand error message and current command usage. + * + * May show full command help instead if the subcommand is a common help option. + * + * @returns RTEXITCODE_SYNTAX, or RTEXITCODE_SUCCESS if common help option. + * @param pszSubcommand The name of the alleged subcommand. + */ +RTEXITCODE errorUnknownSubcommand(const char *pszSubcommand) +{ + Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); + Assert(g_fCurSubcommandScope == RTMSGREFENTRYSTR_SCOPE_GLOBAL); + + /* check if help was requested. */ + if ( strcmp(pszSubcommand, "--help") == 0 + || strcmp(pszSubcommand, "-h") == 0 + || strcmp(pszSubcommand, "-?") == 0) + { + printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + return errorSyntax(Help::tr("Unknown subcommand: %s"), pszSubcommand); +} + + +/** + * Display too many parameters error message and current command usage. + * + * May show full command help instead if the subcommand is a common help option. + * + * @returns RTEXITCODE_SYNTAX, or RTEXITCODE_SUCCESS if common help option. + * @param papszArgs The first unwanted parameter. Terminated by + * NULL entry. + */ +RTEXITCODE errorTooManyParameters(char **papszArgs) +{ + Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); + Assert(g_fCurSubcommandScope != RTMSGREFENTRYSTR_SCOPE_GLOBAL); + + /* check if help was requested. */ + if (papszArgs) + { + for (uint32_t i = 0; papszArgs[i]; i++) + if ( strcmp(papszArgs[i], "--help") == 0 + || strcmp(papszArgs[i], "-h") == 0 + || strcmp(papszArgs[i], "-?") == 0) + { + printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdOut); + return RTEXITCODE_SUCCESS; + } + else if (!strcmp(papszArgs[i], "--")) + break; + } + + return errorSyntax(Help::tr("Too many parameters")); +} + + +/** + * Display current (sub)command usage and the custom error message. + * + * @returns RTEXITCODE_SYNTAX. + * @param pszFormat Custom error message format string. + * @param va Format arguments. + */ +RTEXITCODE errorSyntaxV(const char *pszFormat, va_list va) +{ + Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); + + showLogo(g_pStdErr); + + va_list vaCopy; + va_copy(vaCopy, va); + RTMsgErrorV(pszFormat, vaCopy); + va_end(vaCopy); + + RTStrmPutCh(g_pStdErr, '\n'); + if ( printBriefCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdErr) + >= ERROR_REPEAT_AFTER_USAGE_LENGTH) + { + /* Usage was very long, repeat the error message. */ + RTStrmPutCh(g_pStdErr, '\n'); + RTMsgErrorV(pszFormat, va); + } + return RTEXITCODE_SYNTAX; +} + + +/** + * Display current (sub)command usage and the custom error message. + * + * @returns RTEXITCODE_SYNTAX. + * @param pszFormat Custom error message format string. + * @param ... Format arguments. + */ +RTEXITCODE errorSyntax(const char *pszFormat, ...) +{ + va_list va; + va_start(va, pszFormat); + RTEXITCODE rcExit = errorSyntaxV(pszFormat, va); + va_end(va); + return rcExit; +} + + +/** + * Display current (sub)command usage and the custom error message. + * + * @returns E_INVALIDARG + * @param pszFormat Custom error message format string. + * @param ... Format arguments. + */ +HRESULT errorSyntaxHr(const char *pszFormat, ...) +{ + va_list va; + va_start(va, pszFormat); + errorSyntaxV(pszFormat, va); + va_end(va); + return E_INVALIDARG; +} + + +/** + * Print an error message without the syntax stuff. + * + * @returns RTEXITCODE_SYNTAX. + */ +RTEXITCODE errorArgument(const char *pszFormat, ...) +{ + va_list args; + va_start(args, pszFormat); + RTMsgErrorV(pszFormat, args); + va_end(args); + return RTEXITCODE_SYNTAX; +} + + +/** + * Print an error message without the syntax stuff. + * + * @returns E_INVALIDARG. + */ +HRESULT errorArgumentHr(const char *pszFormat, ...) +{ + va_list args; + va_start(args, pszFormat); + RTMsgErrorV(pszFormat, args); + va_end(args); + return E_INVALIDARG; +} + + +/** + * Worker for errorGetOpt. + * + * @param rcGetOpt The RTGetOpt return value. + * @param pValueUnion The value union returned by RTGetOpt. + */ +static void errorGetOptWorker(int rcGetOpt, union RTGETOPTUNION const *pValueUnion) +{ + if (rcGetOpt == VINF_GETOPT_NOT_OPTION) + RTMsgError(Help::tr("Invalid parameter '%s'"), pValueUnion->psz); + else if (rcGetOpt > 0) + { + if (RT_C_IS_PRINT(rcGetOpt)) + RTMsgError(Help::tr("Invalid option -%c"), rcGetOpt); + else + RTMsgError(Help::tr("Invalid option case %i"), rcGetOpt); + } + else if (rcGetOpt == VERR_GETOPT_UNKNOWN_OPTION) + RTMsgError(Help::tr("Unknown option: %s"), pValueUnion->psz); + else if (rcGetOpt == VERR_GETOPT_INVALID_ARGUMENT_FORMAT) + RTMsgError(Help::tr("Invalid argument format: %s"), pValueUnion->psz); + else if (pValueUnion->pDef) + RTMsgError("%s: %Rrs", pValueUnion->pDef->pszLong, rcGetOpt); + else + RTMsgError("%Rrs", rcGetOpt); +} + + +/** + * For use to deal with RTGetOptFetchValue failures. + * + * @retval RTEXITCODE_SYNTAX + * @param iValueNo The value number being fetched, counting the + * RTGetOpt value as zero and the first + * RTGetOptFetchValue call as one. + * @param pszOption The option being parsed. + * @param rcGetOptFetchValue The status returned by RTGetOptFetchValue. + * @param pValueUnion The value union returned by the fetch. + */ +RTEXITCODE errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion) +{ + Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); + showLogo(g_pStdErr); + if (rcGetOptFetchValue == VERR_GETOPT_REQUIRED_ARGUMENT_MISSING) + RTMsgError(Help::tr("Missing the %u%s value for option %s"), + iValueNo, + iValueNo == 1 ? Help::tr("st") + : iValueNo == 2 ? Help::tr("nd") + : iValueNo == 3 ? Help::tr("rd") + : Help::tr("th"), + pszOption); + else + errorGetOptWorker(rcGetOptFetchValue, pValueUnion); + return RTEXITCODE_SYNTAX; + +} + + +/** + * Handled an RTGetOpt error or common option. + * + * This implements the 'V' and 'h' cases. It reports appropriate syntax errors + * for other @a rcGetOpt values. + * + * @retval RTEXITCODE_SUCCESS if help or version request. + * @retval RTEXITCODE_SYNTAX if not help or version request. + * @param rcGetOpt The RTGetOpt return value. + * @param pValueUnion The value union returned by RTGetOpt. + */ +RTEXITCODE errorGetOpt(int rcGetOpt, union RTGETOPTUNION const *pValueUnion) +{ + Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID); + + /* + * Check if it is an unhandled standard option. + */ + if (rcGetOpt == 'V') + { + RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision()); + return RTEXITCODE_SUCCESS; + } + + if (rcGetOpt == 'h') + { + printFullCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdOut); + return RTEXITCODE_SUCCESS; + } + + /* + * We failed. + */ + showLogo(g_pStdErr); + errorGetOptWorker(rcGetOpt, pValueUnion); + if ( printBriefCommandOrSubcommandHelp(g_enmCurCommand, g_fCurSubcommandScope, g_pStdErr) + >= ERROR_REPEAT_AFTER_USAGE_LENGTH) + { + /* Usage was very long, repeat the error message. */ + RTStrmPutCh(g_pStdErr, '\n'); + errorGetOptWorker(rcGetOpt, pValueUnion); + } + return RTEXITCODE_SYNTAX; +} + + +void showLogo(PRTSTREAM pStrm) +{ + static bool s_fShown; /* show only once */ + + if (!s_fShown) + { + RTStrmPrintf(pStrm, VBOX_PRODUCT " Command Line Management Interface Version " + VBOX_VERSION_STRING "\n" + "Copyright (C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n\n"); + s_fShown = true; + } +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageHostonly.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageHostonly.cpp new file mode 100644 index 00000000..d5b2444d --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageHostonly.cpp @@ -0,0 +1,546 @@ +/* $Id: VBoxManageHostonly.cpp $ */ +/** @file + * VBoxManage - Implementation of hostonlyif command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/cidr.h> +#include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/net.h> +#include <iprt/getopt.h> +#include <iprt/ctype.h> + +#include <VBox/log.h> + +#include "VBoxManage.h" + +DECLARE_TRANSLATION_CONTEXT(HostOnly); + + +using namespace com; + +static const RTGETOPTDEF g_aHostOnlyCreateOptions[] = +{ + { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING }, +}; + +#if defined(VBOX_WITH_NETFLT) && !defined(RT_OS_SOLARIS) +static RTEXITCODE handleCreate(HandlerArg *a) +{ + /* + * Parse input. + */ + bool fMachineReadable = false; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, g_aHostOnlyCreateOptions, + RT_ELEMENTS(g_aHostOnlyCreateOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'M': // --machinereadable + fMachineReadable = true; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* + * Do the work. + */ + ComPtr<IHost> host; + CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IHostNetworkInterface> hif; + ComPtr<IProgress> progress; + + CHECK_ERROR2I_RET(host, CreateHostOnlyNetworkInterface(hif.asOutParam(), progress.asOutParam()), RTEXITCODE_FAILURE); + + if (fMachineReadable) + { + progress->WaitForCompletion(10000); /* Ten seconds should probably be enough. */ + CHECK_PROGRESS_ERROR_RET(progress, (""), RTEXITCODE_FAILURE); + } + else + { + /*HRESULT hrc =*/ showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (HostOnly::tr("Failed to create the host-only adapter")), RTEXITCODE_FAILURE); + } + + Bstr bstrName; + CHECK_ERROR2I(hif, COMGETTER(Name)(bstrName.asOutParam())); + + if (fMachineReadable) + RTPrintf("%ls", bstrName.raw()); + else + RTPrintf(HostOnly::tr("Interface '%ls' was successfully created\n"), bstrName.raw()); + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE handleRemove(HandlerArg *a) +{ + /* + * Parse input. + */ + const char *pszName = NULL; + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, NULL, 0, 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0) + switch (ch) + { + case VINF_GETOPT_NOT_OPTION: + if (pszName) + return errorSyntax(HostOnly::tr("Only one interface name can be specified")); + pszName = ValueUnion.psz; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + if (!pszName) + return errorSyntax(HostOnly::tr("No interface name was specified")); + + /* + * Do the work. + */ + ComPtr<IHost> host; + CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IHostNetworkInterface> hif; + CHECK_ERROR2I_RET(host, FindHostNetworkInterfaceByName(Bstr(pszName).raw(), hif.asOutParam()), RTEXITCODE_FAILURE); + + Bstr guid; + CHECK_ERROR2I_RET(hif, COMGETTER(Id)(guid.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IProgress> progress; + CHECK_ERROR2I_RET(host, RemoveHostOnlyNetworkInterface(guid.raw(), progress.asOutParam()), RTEXITCODE_FAILURE); + + /*HRESULT hrc =*/ showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (HostOnly::tr("Failed to remove the host-only adapter")), RTEXITCODE_FAILURE); + + return RTEXITCODE_SUCCESS; +} +#endif + +static const RTGETOPTDEF g_aHostOnlyIPOptions[] + = { + { "--dhcp", 'd', RTGETOPT_REQ_NOTHING }, + { "-dhcp", 'd', RTGETOPT_REQ_NOTHING }, // deprecated + { "--ip", 'a', RTGETOPT_REQ_STRING }, + { "-ip", 'a', RTGETOPT_REQ_STRING }, // deprecated + { "--netmask", 'm', RTGETOPT_REQ_STRING }, + { "-netmask", 'm', RTGETOPT_REQ_STRING }, // deprecated + { "--ipv6", 'b', RTGETOPT_REQ_STRING }, + { "-ipv6", 'b', RTGETOPT_REQ_STRING }, // deprecated + { "--netmasklengthv6", 'l', RTGETOPT_REQ_UINT8 }, + { "-netmasklengthv6", 'l', RTGETOPT_REQ_UINT8 } // deprecated + }; + +static RTEXITCODE handleIpConfig(HandlerArg *a) +{ + bool fDhcp = false; + bool fNetmasklengthv6 = false; + uint32_t uNetmasklengthv6 = UINT32_MAX; + const char *pszIpv6 = NULL; + const char *pszIp = NULL; + const char *pszNetmask = NULL; + const char *pszName = NULL; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, g_aHostOnlyIPOptions, RT_ELEMENTS(g_aHostOnlyIPOptions), + 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'd': // --dhcp + fDhcp = true; + break; + case 'a': // --ip + if (pszIp) + RTMsgWarning(HostOnly::tr("The --ip option is specified more than once")); + pszIp = ValueUnion.psz; + break; + case 'm': // --netmask + if (pszNetmask) + RTMsgWarning(HostOnly::tr("The --netmask option is specified more than once")); + pszNetmask = ValueUnion.psz; + break; + case 'b': // --ipv6 + if (pszIpv6) + RTMsgWarning(HostOnly::tr("The --ipv6 option is specified more than once")); + pszIpv6 = ValueUnion.psz; + break; + case 'l': // --netmasklengthv6 + if (fNetmasklengthv6) + RTMsgWarning(HostOnly::tr("The --netmasklengthv6 option is specified more than once")); + fNetmasklengthv6 = true; + uNetmasklengthv6 = ValueUnion.u8; + break; + case VINF_GETOPT_NOT_OPTION: + if (pszName) + return errorSyntax(HostOnly::tr("Only one interface name can be specified")); + pszName = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* parameter sanity check */ + if (fDhcp && (fNetmasklengthv6 || pszIpv6 || pszIp || pszNetmask)) + return errorSyntax(HostOnly::tr("You can not use --dhcp with static ip configuration parameters: --ip, --netmask, --ipv6 and --netmasklengthv6.")); + if ((pszIp || pszNetmask) && (fNetmasklengthv6 || pszIpv6)) + return errorSyntax(HostOnly::tr("You can not use ipv4 configuration (--ip and --netmask) with ipv6 (--ipv6 and --netmasklengthv6) simultaneously.")); + + ComPtr<IHost> host; + CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IHostNetworkInterface> hif; + CHECK_ERROR2I_RET(host, FindHostNetworkInterfaceByName(Bstr(pszName).raw(), hif.asOutParam()), RTEXITCODE_FAILURE); + if (hif.isNull()) + return errorArgument(HostOnly::tr("Could not find interface '%s'"), pszName); + + if (fDhcp) + CHECK_ERROR2I_RET(hif, EnableDynamicIPConfig(), RTEXITCODE_FAILURE); + else if (pszIp) + { + if (!pszNetmask) + pszNetmask = "255.255.255.0"; /* ?? */ + CHECK_ERROR2I_RET(hif, EnableStaticIPConfig(Bstr(pszIp).raw(), Bstr(pszNetmask).raw()), RTEXITCODE_FAILURE); + } + else if (pszIpv6) + { + BOOL fIpV6Supported; + CHECK_ERROR2I_RET(hif, COMGETTER(IPV6Supported)(&fIpV6Supported), RTEXITCODE_FAILURE); + if (!fIpV6Supported) + { + RTMsgError(HostOnly::tr("IPv6 setting is not supported for this adapter")); + return RTEXITCODE_FAILURE; + } + + if (uNetmasklengthv6 == UINT32_MAX) + uNetmasklengthv6 = 64; /* ?? */ + CHECK_ERROR2I_RET(hif, EnableStaticIPConfigV6(Bstr(pszIpv6).raw(), (ULONG)uNetmasklengthv6), RTEXITCODE_FAILURE); + } + else + return errorSyntax(HostOnly::tr("Neither -dhcp nor -ip nor -ipv6 was specfified")); + + return RTEXITCODE_SUCCESS; +} + + +RTEXITCODE handleHostonlyIf(HandlerArg *a) +{ + if (a->argc < 1) + return errorSyntax(HostOnly::tr("No sub-command specified")); + + RTEXITCODE rcExit; + if (!strcmp(a->argv[0], "ipconfig")) + { + setCurrentSubcommand(HELP_SCOPE_HOSTONLYIF_IPCONFIG); + rcExit = handleIpConfig(a); + } +#if defined(VBOX_WITH_NETFLT) && !defined(RT_OS_SOLARIS) + else if (!strcmp(a->argv[0], "create")) + { + setCurrentSubcommand(HELP_SCOPE_HOSTONLYIF_CREATE); + rcExit = handleCreate(a); + } + else if (!strcmp(a->argv[0], "remove")) + { + setCurrentSubcommand(HELP_SCOPE_HOSTONLYIF_REMOVE); + rcExit = handleRemove(a); + } +#endif + else + rcExit = errorSyntax(HostOnly::tr("Unknown sub-command '%s'"), a->argv[0]); + return rcExit; +} + +#ifdef VBOX_WITH_VMNET +struct HostOnlyNetworkOptions +{ + bool fEnable; + bool fDisable; + Bstr bstrNetworkId; + Bstr bstrNetworkName; + Bstr bstrNetworkMask; + Bstr bstrLowerIp; + Bstr bstrUpperIp; + /* Initialize fEnable and fDisable */ + HostOnlyNetworkOptions() : fEnable(false), fDisable(false) {}; +}; +typedef struct HostOnlyNetworkOptions HOSTONLYNETOPT; + +static RTEXITCODE createUpdateHostOnlyNetworkParse(HandlerArg *a, HOSTONLYNETOPT& options) +{ + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--netmask", 'm', RTGETOPT_REQ_STRING }, + { "--lower-ip", 'l', RTGETOPT_REQ_STRING }, + { "--lowerip", 'l', RTGETOPT_REQ_STRING }, + { "--upper-ip", 'u', RTGETOPT_REQ_STRING }, + { "--upperip", 'u', RTGETOPT_REQ_STRING }, + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "--disable", 'd', RTGETOPT_REQ_NOTHING }, + }; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* iFirst */, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + options.bstrNetworkId = ValueUnion.psz; + break; + case 'n': + options.bstrNetworkName = ValueUnion.psz; + break; + case 'm': + options.bstrNetworkMask = ValueUnion.psz; + break; + case 'l': + options.bstrLowerIp = ValueUnion.psz; + break; + case 'u': + options.bstrUpperIp = ValueUnion.psz; + break; + case 'e': + options.fEnable = true; + break; + case 'd': + options.fDisable = true; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE createUpdateHostOnlyNetworkCommon(ComPtr<IHostOnlyNetwork> hostOnlyNetwork, HOSTONLYNETOPT& options) +{ + HRESULT hrc = S_OK; + + if (options.bstrNetworkId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(Id)(options.bstrNetworkId.raw()), RTEXITCODE_FAILURE); + } + if (options.bstrNetworkName.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(NetworkName)(options.bstrNetworkName.raw()), RTEXITCODE_FAILURE); + } + if (options.bstrNetworkMask.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(NetworkMask)(options.bstrNetworkMask.raw()), RTEXITCODE_FAILURE); + } + if (options.bstrLowerIp.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(LowerIP)(options.bstrLowerIp.raw()), RTEXITCODE_FAILURE); + } + if (options.bstrUpperIp.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(UpperIP)(options.bstrUpperIp.raw()), RTEXITCODE_FAILURE); + } + if (options.fEnable) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE); + } + if (options.fDisable) + { + CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE); + } + + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE handleNetAdd(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + HOSTONLYNETOPT options; + hrc = createUpdateHostOnlyNetworkParse(a, options); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<IHostOnlyNetwork> hostOnlyNetwork; + + if (options.bstrNetworkName.isEmpty()) + return errorArgument(HostOnly::tr("The --name parameter must be specified")); + if (options.bstrNetworkMask.isEmpty()) + return errorArgument(HostOnly::tr("The --netmask parameter must be specified")); + if (options.bstrLowerIp.isEmpty()) + return errorArgument(HostOnly::tr("The --lower-ip parameter must be specified")); + if (options.bstrUpperIp.isEmpty()) + return errorArgument(HostOnly::tr("The --upper-ip parameter must be specified")); + + CHECK_ERROR2_RET(hrc, pVirtualBox, + CreateHostOnlyNetwork(options.bstrNetworkName.raw(), hostOnlyNetwork.asOutParam()), + RTEXITCODE_FAILURE); + return createUpdateHostOnlyNetworkCommon(hostOnlyNetwork, options); +} + +static RTEXITCODE handleNetModify(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + HOSTONLYNETOPT options; + hrc = createUpdateHostOnlyNetworkParse(a, options); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<IHostOnlyNetwork> hostOnlyNetwork; + + if (options.bstrNetworkName.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindHostOnlyNetworkByName(options.bstrNetworkName.raw(), hostOnlyNetwork.asOutParam()), + RTEXITCODE_FAILURE); + } + else if (options.bstrNetworkId.isNotEmpty()) + { + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindHostOnlyNetworkById(options.bstrNetworkId.raw(), hostOnlyNetwork.asOutParam()), + RTEXITCODE_FAILURE); + } + else + return errorArgument(HostOnly::tr("Either --name or --id parameter must be specified")); + + return createUpdateHostOnlyNetworkCommon(hostOnlyNetwork, options); +} + +static RTEXITCODE handleNetRemove(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + static const RTGETOPTDEF s_aOptions[] = + { + { "--id", 'i', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + }; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* iFirst */, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + Bstr strNetworkId, strNetworkName; + + int c; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': + strNetworkId=ValueUnion.psz; + break; + case 'n': + strNetworkName=ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + default: + return errorGetOpt(c, &ValueUnion); + } + } + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<IHostOnlyNetwork> hostOnlyNetwork; + + if (!strNetworkName.isEmpty()) + { + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindHostOnlyNetworkByName(strNetworkName.raw(), hostOnlyNetwork.asOutParam()), + RTEXITCODE_FAILURE); + } + else if (!strNetworkId.isEmpty()) + { + CHECK_ERROR2_RET(hrc, pVirtualBox, + FindHostOnlyNetworkById(strNetworkId.raw(), hostOnlyNetwork.asOutParam()), + RTEXITCODE_FAILURE); + } + else + return errorArgument(HostOnly::tr("Either --name or --id parameter must be specified")); + + CHECK_ERROR2_RET(hrc, pVirtualBox, + RemoveHostOnlyNetwork(hostOnlyNetwork), + RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + +RTEXITCODE handleHostonlyNet(HandlerArg *a) +{ + if (a->argc < 1) + return errorSyntax(HostOnly::tr("No sub-command specified")); + + RTEXITCODE rcExit; + if (!strcmp(a->argv[0], "add")) + { + setCurrentSubcommand(HELP_SCOPE_HOSTONLYNET_ADD); + rcExit = handleNetAdd(a); + } + else if (!strcmp(a->argv[0], "modify")) + { + setCurrentSubcommand(HELP_SCOPE_HOSTONLYNET_MODIFY); + rcExit = handleNetModify(a); + } + else if (!strcmp(a->argv[0], "remove")) + { + setCurrentSubcommand(HELP_SCOPE_HOSTONLYNET_REMOVE); + rcExit = handleNetRemove(a); + } + else + rcExit = errorSyntax(HostOnly::tr("Unknown sub-command '%s'"), a->argv[0]); + return rcExit; +} +#endif /* VBOX_WITH_VMNET */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp new file mode 100644 index 00000000..524c1be2 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp @@ -0,0 +1,3231 @@ +/* $Id: VBoxManageInfo.cpp $ */ +/** @file + * VBoxManage - The 'showvminfo' command and helper routines. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> + +#include <VBox/com/VirtualBox.h> + +#ifdef VBOX_WITH_PCI_PASSTHROUGH +#include <VBox/pci.h> +#endif + +#include <VBox/log.h> +#include <VBox/version.h> +#include <iprt/stream.h> +#include <iprt/time.h> +#include <iprt/string.h> +#include <iprt/getopt.h> +#include <iprt/ctype.h> + +#include "VBoxManage.h" +#include "VBoxManageUtils.h" + +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Info); + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +#define SHOW_UTF8_STRING(a_pszMachine, a_pszHuman, a_szValue) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, a_szValue); \ + else \ + RTPrintf("%-28s %s\n", a_pszHuman, a_szValue); \ + } while (0) + +#define SHOW_BSTR_STRING(a_pszMachine, a_pszHuman, a_bstrValue) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, &a_bstrValue); \ + else \ + RTPrintf("%-28s %ls\n", a_pszHuman, a_bstrValue.raw()); \ + } while (0) + +#define SHOW_BOOL_VALUE_EX(a_pszMachine, a_pszHuman, a_fValue, a_szTrue, a_szFalse) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, a_fValue ? "on" : "off"); \ + else \ + RTPrintf("%-28s %s\n", a_pszHuman, a_fValue ? a_szTrue: a_szFalse); \ + } while (0) + +#define SHOW_BOOL_VALUE(a_pszMachine, a_pszHuman, a_fValue) \ + SHOW_BOOL_VALUE_EX(a_pszMachine, a_pszHuman, a_fValue, Info::tr("enabled"), Info::tr("disabled")) + +#define SHOW_ULONG_VALUE(a_pszMachine, a_pszHuman, a_uValue, a_pszUnit) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + if (details == VMINFO_MACHINEREADABLE) \ + RTPrintf("%s=%u\n", a_pszMachine, a_uValue); \ + else \ + RTPrintf("%-28s %u%s\n", a_pszHuman, a_uValue, a_pszUnit); \ + } while (0) + +#define SHOW_LONG64_VALUE(a_pszMachine, a_pszHuman, a_llValue, a_pszUnit) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + if (details == VMINFO_MACHINEREADABLE) \ + RTPrintf("%s=%lld\n", a_pszMachine, a_llValue); \ + else \ + RTPrintf("%-28s %lld%s\n", a_pszHuman, a_llValue, a_pszUnit); \ + } while (0) + +#define SHOW_BOOLEAN_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \ + SHOW_BOOLEAN_PROP_EX(a_pObj, a_Prop, a_pszMachine, a_pszHuman, Info::tr("enabled"), Info::tr("disabled")) + +#define SHOW_BOOLEAN_PROP_EX(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_szTrue, a_szFalse) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + BOOL f; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&f), hrcCheck); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, f ? "on" : "off"); \ + else \ + RTPrintf("%-28s %s\n", a_pszHuman, f ? a_szTrue : a_szFalse); \ + } while (0) + +#define SHOW_BOOLEAN_METHOD(a_pObj, a_Invocation, a_pszMachine, a_pszHuman) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + BOOL f; \ + CHECK_ERROR2I_RET(a_pObj, a_Invocation, hrcCheck); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, f ? "on" : "off"); \ + else \ + RTPrintf("%-28s %s\n", a_pszHuman, f ? Info::tr("enabled") : Info::tr("disabled")); \ + } while (0) + +#define SHOW_STRING_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + Bstr bstr; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, &bstr); \ + else \ + RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \ + } while (0) + +#define SHOW_STRING_PROP_NOT_EMPTY(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + Bstr bstr; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \ + if (bstr.isNotEmpty()) \ + { \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, &bstr); \ + else \ + RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \ + } \ + } while (0) + + /** @def SHOW_STRING_PROP_MAJ + * For not breaking the output in a dot release we don't show default values. */ +#define SHOW_STRING_PROP_MAJ(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnless, a_uMajorVer) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + Bstr bstr; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(bstr.asOutParam()), hrcCheck); \ + if ((a_uMajorVer) <= VBOX_VERSION_MAJOR || !bstr.equals(a_pszUnless)) \ + { \ + if (details == VMINFO_MACHINEREADABLE)\ + outputMachineReadableString(a_pszMachine, &bstr); \ + else \ + RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \ + } \ + } while (0) + +#define SHOW_STRINGARRAY_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + SafeArray<BSTR> array; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(ComSafeArrayAsOutParam(array)), hrcCheck); \ + Utf8Str str; \ + for (size_t i = 0; i < array.size(); i++) \ + { \ + if (i != 0) \ + str.append(","); \ + str.append(Utf8Str(array[i]).c_str()); \ + } \ + Bstr bstr(str); \ + if (details == VMINFO_MACHINEREADABLE) \ + outputMachineReadableString(a_pszMachine, &bstr); \ + else \ + RTPrintf("%-28s %ls\n", a_pszHuman, bstr.raw()); \ + } while (0) + +#define SHOW_UUID_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) \ + SHOW_STRING_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman) + +#define SHOW_USHORT_PROP_EX2(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnit, a_szFmtMachine, a_szFmtHuman) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + USHORT u16 = 0; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&u16), hrcCheck); \ + if (details == VMINFO_MACHINEREADABLE) \ + RTPrintf("%s=" a_szFmtMachine "\n", a_pszMachine, u16); \ + else \ + RTPrintf("%-28s " a_szFmtHuman "%s\n", a_pszHuman, u16, u16, a_pszUnit); \ + } while (0) + +#define SHOW_ULONG_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnit) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + ULONG u32 = 0; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&u32), hrcCheck); \ + if (details == VMINFO_MACHINEREADABLE) \ + RTPrintf("%s=%u\n", a_pszMachine, u32); \ + else \ + RTPrintf("%-28s %u%s\n", a_pszHuman, u32, a_pszUnit); \ + } while (0) + +#define SHOW_LONG64_PROP(a_pObj, a_Prop, a_pszMachine, a_pszHuman, a_pszUnit) \ + do \ + { \ + Assert(a_pszHuman[strlen(a_pszHuman) - 1] == ':'); \ + LONG64 i64 = 0; \ + CHECK_ERROR2I_RET(a_pObj, COMGETTER(a_Prop)(&i64), hrcCheck); \ + if (details == VMINFO_MACHINEREADABLE) \ + RTPrintf("%s=%lld\n", a_pszMachine, i64); \ + else \ + RTPrintf("%-28s %'lld%s\n", a_pszHuman, i64, a_pszUnit); \ + } while (0) + + +// funcs +/////////////////////////////////////////////////////////////////////////////// + +/** + * Helper for formatting an indexed name or some such thing. + */ +static const char *FmtNm(char psz[80], const char *pszFormat, ...) +{ + va_list va; + va_start(va, pszFormat); + RTStrPrintfV(psz, 80, pszFormat, va); + va_end(va); + return psz; +} + +HRESULT showSnapshots(ComPtr<ISnapshot> &rootSnapshot, + ComPtr<ISnapshot> ¤tSnapshot, + VMINFO_DETAILS details, + const Utf8Str &prefix /* = ""*/, + int level /*= 0*/) +{ + /* start with the root */ + Bstr name; + Bstr uuid; + Bstr description; + CHECK_ERROR2I_RET(rootSnapshot, COMGETTER(Name)(name.asOutParam()), hrcCheck); + CHECK_ERROR2I_RET(rootSnapshot, COMGETTER(Id)(uuid.asOutParam()), hrcCheck); + CHECK_ERROR2I_RET(rootSnapshot, COMGETTER(Description)(description.asOutParam()), hrcCheck); + bool fCurrent = (rootSnapshot == currentSnapshot); + if (details == VMINFO_MACHINEREADABLE) + { + /* print with hierarchical numbering */ + RTPrintf("SnapshotName%s=\"%ls\"\n", prefix.c_str(), name.raw()); + RTPrintf("SnapshotUUID%s=\"%s\"\n", prefix.c_str(), Utf8Str(uuid).c_str()); + if (!description.isEmpty()) + RTPrintf("SnapshotDescription%s=\"%ls\"\n", prefix.c_str(), description.raw()); + if (fCurrent) + { + RTPrintf("CurrentSnapshotName=\"%ls\"\n", name.raw()); + RTPrintf("CurrentSnapshotUUID=\"%s\"\n", Utf8Str(uuid).c_str()); + RTPrintf("CurrentSnapshotNode=\"SnapshotName%s\"\n", prefix.c_str()); + } + } + else + { + /* print with indentation */ + RTPrintf(Info::tr(" %sName: %ls (UUID: %s)%s\n"), + prefix.c_str(), + name.raw(), + Utf8Str(uuid).c_str(), + (fCurrent) ? " *" : ""); + if (!description.isEmpty() && RTUtf16Chr(description.raw(), '\n') == NULL) + RTPrintf(Info::tr(" %sDescription: %ls\n"), prefix.c_str(), description.raw()); + else if (!description.isEmpty()) + RTPrintf(Info::tr(" %sDescription:\n%ls\n"), prefix.c_str(), description.raw()); + } + + /* get the children */ + HRESULT hrc = S_OK; + SafeIfaceArray <ISnapshot> coll; + CHECK_ERROR2I_RET(rootSnapshot,COMGETTER(Children)(ComSafeArrayAsOutParam(coll)), hrcCheck); + if (!coll.isNull()) + { + for (size_t index = 0; index < coll.size(); ++index) + { + ComPtr<ISnapshot> snapshot = coll[index]; + if (snapshot) + { + Utf8Str newPrefix; + if (details == VMINFO_MACHINEREADABLE) + newPrefix.printf("%s-%d", prefix.c_str(), index + 1); + else + newPrefix.printf("%s ", prefix.c_str()); + + /* recursive call */ + HRESULT hrc2 = showSnapshots(snapshot, currentSnapshot, details, newPrefix, level + 1); + if (FAILED(hrc2)) + hrc = hrc2; + } + } + } + return hrc; +} + +static void makeTimeStr(char *s, int cb, int64_t millies) +{ + RTTIME t; + RTTIMESPEC ts; + + RTTimeSpecSetMilli(&ts, millies); + + RTTimeExplode(&t, &ts); + + RTStrPrintf(s, cb, "%04d/%02d/%02d %02d:%02d:%02d UTC", + t.i32Year, t.u8Month, t.u8MonthDay, + t.u8Hour, t.u8Minute, t.u8Second); +} + +const char *machineStateToName(MachineState_T machineState, bool fShort) +{ + switch (machineState) + { + case MachineState_PoweredOff: + return fShort ? "poweroff" : Info::tr("powered off"); + case MachineState_Saved: + return fShort ? "saved" : Info::tr("saved"); + case MachineState_Teleported: + return fShort ? "teleported" : Info::tr("teleported"); + case MachineState_Aborted: + return fShort ? "aborted" : Info::tr("aborted"); + case MachineState_AbortedSaved: + return fShort ? "aborted-saved" : Info::tr("aborted-saved"); + case MachineState_Running: + return fShort ? "running" : Info::tr("running"); + case MachineState_Paused: + return fShort ? "paused" : Info::tr("paused"); + case MachineState_Stuck: + return fShort ? "gurumeditation" : Info::tr("guru meditation"); + case MachineState_Teleporting: + return fShort ? "teleporting" : Info::tr("teleporting"); + case MachineState_LiveSnapshotting: + return fShort ? "livesnapshotting" : Info::tr("live snapshotting"); + case MachineState_Starting: + return fShort ? "starting" : Info::tr("starting"); + case MachineState_Stopping: + return fShort ? "stopping" : Info::tr("stopping"); + case MachineState_Saving: + return fShort ? "saving" : Info::tr("saving"); + case MachineState_Restoring: + return fShort ? "restoring" : Info::tr("restoring"); + case MachineState_TeleportingPausedVM: + return fShort ? "teleportingpausedvm" : Info::tr("teleporting paused vm"); + case MachineState_TeleportingIn: + return fShort ? "teleportingin" : Info::tr("teleporting (incoming)"); + case MachineState_DeletingSnapshotOnline: + return fShort ? "deletingsnapshotlive" : Info::tr("deleting snapshot live"); + case MachineState_DeletingSnapshotPaused: + return fShort ? "deletingsnapshotlivepaused" : Info::tr("deleting snapshot live paused"); + case MachineState_OnlineSnapshotting: + return fShort ? "onlinesnapshotting" : Info::tr("online snapshotting"); + case MachineState_RestoringSnapshot: + return fShort ? "restoringsnapshot" : Info::tr("restoring snapshot"); + case MachineState_DeletingSnapshot: + return fShort ? "deletingsnapshot" : Info::tr("deleting snapshot"); + case MachineState_SettingUp: + return fShort ? "settingup" : Info::tr("setting up"); + case MachineState_Snapshotting: + return fShort ? "snapshotting" : Info::tr("offline snapshotting"); + default: + break; + } + return Info::tr("unknown"); +} + +const char *facilityStateToName(AdditionsFacilityStatus_T faStatus, bool fShort) +{ + switch (faStatus) + { + case AdditionsFacilityStatus_Inactive: + return fShort ? "inactive" : Info::tr("not active"); + case AdditionsFacilityStatus_Paused: + return fShort ? "paused" : Info::tr("paused"); + case AdditionsFacilityStatus_PreInit: + return fShort ? "preinit" : Info::tr("pre-initializing"); + case AdditionsFacilityStatus_Init: + return fShort ? "init" : Info::tr("initializing"); + case AdditionsFacilityStatus_Active: + return fShort ? "active" : Info::tr("active/running"); + case AdditionsFacilityStatus_Terminating: + return fShort ? "terminating" : Info::tr("terminating"); + case AdditionsFacilityStatus_Terminated: + return fShort ? "terminated" : Info::tr("terminated"); + case AdditionsFacilityStatus_Failed: + return fShort ? "failed" : Info::tr("failed"); + case AdditionsFacilityStatus_Unknown: + default: + break; + } + return Info::tr("unknown"); +} + +static const char *storageControllerTypeToName(StorageControllerType_T enmCtlType, bool fMachineReadable = false) +{ + switch (enmCtlType) + { + case StorageControllerType_LsiLogic: + return "LsiLogic"; + case StorageControllerType_LsiLogicSas: + return "LsiLogicSas"; + case StorageControllerType_BusLogic: + return "BusLogic"; + case StorageControllerType_IntelAhci: + return "IntelAhci"; + case StorageControllerType_PIIX3: + return "PIIX3"; + case StorageControllerType_PIIX4: + return "PIIX4"; + case StorageControllerType_ICH6: + return "ICH6"; + case StorageControllerType_I82078: + return "I82078"; + case StorageControllerType_USB: + return "USB"; + case StorageControllerType_NVMe: + return "NVMe"; + case StorageControllerType_VirtioSCSI: + return "VirtioSCSI"; + default: + return fMachineReadable ? "unknown" : Info::tr("unknown"); + } +} + + +DECLINLINE(bool) doesMachineReadableStringNeedEscaping(const char *psz) +{ + return psz == NULL + || *psz == '\0' + || strchr(psz, '"') != NULL + || strchr(psz, '\\') != NULL; +} + + +/** + * This simply outputs the string adding necessary escaping and nothing else. + */ +void outputMachineReadableStringWorker(const char *psz) +{ + for (;;) + { + const char *pszDoubleQuote = strchr(psz, '"'); + const char *pszSlash = strchr(psz, '\\'); + const char *pszNext; + if (pszSlash) + pszNext = !pszDoubleQuote || (uintptr_t)pszSlash < (uintptr_t)pszDoubleQuote ? pszSlash : pszDoubleQuote; + else if (pszDoubleQuote) + pszNext = pszDoubleQuote; + else + { + RTStrmWrite(g_pStdOut, psz, strlen(psz)); + break; + } + RTStrmWrite(g_pStdOut, psz, pszNext - psz); + char const szTmp[2] = { '\\', *pszNext }; + RTStrmWrite(g_pStdOut, szTmp, sizeof(szTmp)); + + psz = pszNext + 1; + } +} + + +/** + * This takes care of escaping double quotes and slashes that the string might + * contain. + * + * @param pszName The variable name. + * @param pszValue The value. + * @param fQuoteName Whether to unconditionally quote the name or not. + * @param fNewline Whether to automatically add a newline after the value. + */ +void outputMachineReadableString(const char *pszName, const char *pszValue, bool fQuoteName /*=false*/, bool fNewline /*=true*/) +{ + if (!fQuoteName) + fQuoteName = strchr(pszName, '=') != NULL; + bool const fEscapeName = doesMachineReadableStringNeedEscaping(pszName); + bool const fEscapeValue = doesMachineReadableStringNeedEscaping(pszValue); + if (!fEscapeName && !fEscapeValue) + { + if (fNewline) + RTPrintf(!fQuoteName ? "%s=\"%s\"\n" : "\"%s\"=\"%s\"\n", pszName, pszValue); + else + RTPrintf(!fQuoteName ? "%s=\"%s\"" : "\"%s\"=\"%s\"", pszName, pszValue); + } + else + { + /* The name and string quotation: */ + if (!fEscapeName) + RTPrintf(fQuoteName ? "\"%s\"=\"" : "%s=\"", pszName); + else + { + if (fQuoteName) + RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\"")); + outputMachineReadableStringWorker(pszName); + if (fQuoteName) + RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\"=\"")); + else + RTStrmWrite(g_pStdOut, RT_STR_TUPLE("=\"")); + } + + /* the value and the closing quotation */ + outputMachineReadableStringWorker(pszValue); + if (fNewline) + RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\"\n")); + else + RTStrmWrite(g_pStdOut, RT_STR_TUPLE("\"")); + } +} + + +/** + * This takes care of escaping double quotes and slashes that the string might + * contain. + * + * @param pszName The variable name. + * @param pbstrValue The value. + * @param fQuoteName Whether to unconditionally quote the name or not. + * @param fNewline Whether to automatically add a newline after the value. + */ +void outputMachineReadableString(const char *pszName, Bstr const *pbstrValue, bool fQuoteName /*=false*/, bool fNewline /*=true*/) +{ + com::Utf8Str strValue(*pbstrValue); + outputMachineReadableString(pszName, strValue.c_str(), fQuoteName, fNewline); +} + + +/** + * Variant that allows formatting the name string, C string value. + * + * @param pszValue The value. + * @param fQuoteName Whether to unconditionally quote the name or not. + * @param pszNameFmt The variable name. + */ +void outputMachineReadableStringWithFmtName(const char *pszValue, bool fQuoteName, const char *pszNameFmt, ...) +{ + com::Utf8Str strName; + va_list va; + va_start(va, pszNameFmt); + strName.printfV(pszNameFmt, va); + va_end(va); + + outputMachineReadableString(strName.c_str(), pszValue, fQuoteName); +} + + +/** + * Variant that allows formatting the name string, Bstr value. + * + * @param pbstrValue The value. + * @param fQuoteName Whether to unconditionally quote the name or not. + * @param pszNameFmt The variable name. + */ +void outputMachineReadableStringWithFmtName(com::Bstr const *pbstrValue, bool fQuoteName, const char *pszNameFmt, ...) +{ + com::Utf8Str strName; + va_list va; + va_start(va, pszNameFmt); + strName.printfV(pszNameFmt, va); + va_end(va); + + outputMachineReadableString(strName.c_str(), pbstrValue, fQuoteName); +} + + +/** + * Machine readable outputting of a boolean value. + */ +void outputMachineReadableBool(const char *pszName, BOOL const *pfValue) +{ + RTPrintf("%s=\"%s\"\n", pszName, *pfValue ? "on" : "off"); +} + + +/** + * Machine readable outputting of a boolean value. + */ +void outputMachineReadableBool(const char *pszName, bool const *pfValue) +{ + RTPrintf("%s=\"%s\"\n", pszName, *pfValue ? "on" : "off"); +} + + +/** + * Machine readable outputting of a ULONG value. + */ +void outputMachineReadableULong(const char *pszName, ULONG *puValue) +{ + RTPrintf("%s=\"%u\"\n", pszName, *puValue); +} + + +/** + * Machine readable outputting of a LONG64 value. + */ +void outputMachineReadableLong64(const char *pszName, LONG64 *puValue) +{ + RTPrintf("%s=\"%llu\"\n", pszName, *puValue); +} + + +/** + * Helper for parsing extra data config. + * @returns true, false, or -1 if invalid. + */ +static int parseCfgmBool(Bstr const *pbstr) +{ + /* GetExtraData returns empty strings if the requested data wasn't + found, so fend that off first: */ + size_t cwcLeft = pbstr->length(); + if (!cwcLeft) + return false; + PCRTUTF16 pwch = pbstr->raw(); + + /* Skip type prefix: */ + if ( cwcLeft >= 8 + && pwch[0] == 'i' + && pwch[1] == 'n' + && pwch[2] == 't' + && pwch[3] == 'e' + && pwch[4] == 'g' + && pwch[5] == 'e' + && pwch[6] == 'r' + && pwch[7] == ':') + { + pwch += 8; + cwcLeft -= 8; + } + + /* Hex prefix? */ + bool fHex = false; + if ( cwcLeft >= 2 + && pwch[0] == '0' + && (pwch[1] == 'x' || pwch[1] == 'X')) + { + pwch += 2; + cwcLeft -= 2; + fHex = true; + } + + /* Empty string is wrong: */ + if (cwcLeft == 0) + return -1; + + /* Check that it's all digits and return when we find a non-zero + one or reaches the end: */ + do + { + RTUTF16 const wc = *pwch++; + if (!RT_C_IS_DIGIT(wc) && (!fHex || !RT_C_IS_XDIGIT(wc))) + return -1; + if (wc != '0') + return true; + } while (--cwcLeft > 0); + return false; +} + + +/** + * Converts bandwidth group type to a string. + * @returns String representation. + * @param enmType Bandwidth control group type. + */ +static const char * bwGroupTypeToString(BandwidthGroupType_T enmType) +{ + switch (enmType) + { + case BandwidthGroupType_Null: return Info::tr("Null"); + case BandwidthGroupType_Disk: return Info::tr("Disk"); + case BandwidthGroupType_Network: return Info::tr("Network"); +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case BandwidthGroupType_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + return Info::tr("unknown"); +} + +HRESULT showBandwidthGroups(ComPtr<IBandwidthControl> &bwCtrl, + VMINFO_DETAILS details) +{ + SafeIfaceArray<IBandwidthGroup> bwGroups; + CHECK_ERROR2I_RET(bwCtrl, GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)), hrcCheck); + + if (details != VMINFO_MACHINEREADABLE) + RTPrintf(bwGroups.size() != 0 ? "\n" : Info::tr("<none>\n")); + for (size_t i = 0; i < bwGroups.size(); i++) + { + Bstr strName; + CHECK_ERROR2I_RET(bwGroups[i], COMGETTER(Name)(strName.asOutParam()), hrcCheck); + BandwidthGroupType_T enmType; + CHECK_ERROR2I_RET(bwGroups[i], COMGETTER(Type)(&enmType), hrcCheck); + LONG64 cbMaxPerSec; + CHECK_ERROR2I_RET(bwGroups[i], COMGETTER(MaxBytesPerSec)(&cbMaxPerSec), hrcCheck); + + const char *pszType = bwGroupTypeToString(enmType); + if (details == VMINFO_MACHINEREADABLE) + { + /* Complicated condensed format. */ + char szName[64]; + RTStrPrintf(szName, sizeof(szName), "BandwidthGroup%zu", i); + outputMachineReadableString(szName, &strName, false /*fQuoteName*/, false /*fNewline*/); + RTPrintf(",%s,%RI64\n", pszType, cbMaxPerSec); + } + else + { + if (cbMaxPerSec == 0) + { + RTPrintf(Info::tr("#%zu: Name: '%ls', Type: %s, Limit: none (disabled)\n"), i, strName.raw(), pszType); + continue; + } + + /* translate to human readable units.*/ + const char *pszUnit; + LONG64 cUnits; + if (!(cbMaxPerSec % _1G)) + { + cUnits = cbMaxPerSec / _1G; + pszUnit = "GiB/s"; + } + else if (!(cbMaxPerSec % _1M)) + { + cUnits = cbMaxPerSec / _1M; + pszUnit = "MiB/s"; + } + else if (!(cbMaxPerSec % _1K)) + { + cUnits = cbMaxPerSec / _1K; + pszUnit = "KiB/s"; + } + else + { + cUnits = cbMaxPerSec; + pszUnit = "bytes/s"; + } + + /* + * We want to report network rate limit in bits/s, not bytes. + * Only if it cannot be express it in kilobits we will fall + * back to reporting it in bytes. + */ + if ( enmType == BandwidthGroupType_Network + && !(cbMaxPerSec % 125) ) + { + LONG64 cNetUnits = cbMaxPerSec / 125; + const char *pszNetUnit = "kbps"; + if (!(cNetUnits % 1000000)) + { + cNetUnits /= 1000000; + pszNetUnit = "Gbps"; + } + else if (!(cNetUnits % 1000)) + { + cNetUnits /= 1000; + pszNetUnit = "Mbps"; + } + RTPrintf(Info::tr("#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s (%RI64 %s)\n"), + i, strName.raw(), pszType, cNetUnits, pszNetUnit, cUnits, pszUnit); + } + else + RTPrintf(Info::tr("#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s\n"), i, strName.raw(), pszType, cUnits, pszUnit); + } + } + + return VINF_SUCCESS; +} + +/** Shows a shared folder. */ +static HRESULT showSharedFolder(ComPtr<ISharedFolder> &sf, VMINFO_DETAILS details, const char *pszDesc, + const char *pszMrInfix, size_t idxMr, bool fFirst) +{ + Bstr name, hostPath, bstrAutoMountPoint; + BOOL writable = FALSE, fAutoMount = FALSE; + CHECK_ERROR2I_RET(sf, COMGETTER(Name)(name.asOutParam()), hrcCheck); + CHECK_ERROR2I_RET(sf, COMGETTER(HostPath)(hostPath.asOutParam()), hrcCheck); + CHECK_ERROR2I_RET(sf, COMGETTER(Writable)(&writable), hrcCheck); + CHECK_ERROR2I_RET(sf, COMGETTER(AutoMount)(&fAutoMount), hrcCheck); + CHECK_ERROR2I_RET(sf, COMGETTER(AutoMountPoint)(bstrAutoMountPoint.asOutParam()), hrcCheck); + + if (fFirst && details != VMINFO_MACHINEREADABLE) + RTPrintf("\n\n"); + if (details == VMINFO_MACHINEREADABLE) + { + char szNm[80]; + outputMachineReadableString(FmtNm(szNm, "SharedFolderName%s%zu", pszMrInfix, idxMr), &name); + outputMachineReadableString(FmtNm(szNm, "SharedFolderPath%s%zu", pszMrInfix, idxMr), &hostPath); + } + else + { + RTPrintf(Info::tr("Name: '%ls', Host path: '%ls' (%s), %s%s"), + name.raw(), hostPath.raw(), pszDesc, writable ? Info::tr("writable") : Info::tr("readonly"), + fAutoMount ? Info::tr(", auto-mount") : ""); + if (bstrAutoMountPoint.isNotEmpty()) + RTPrintf(Info::tr(", mount-point: '%ls'\n"), bstrAutoMountPoint.raw()); + else + RTPrintf("\n"); + } + return S_OK; +} + +/** Displays a list of IUSBDevices or IHostUSBDevices. */ +template <class IUSBDeviceType> +static HRESULT showUsbDevices(SafeIfaceArray<IUSBDeviceType> &coll, const char *pszPfx, + const char *pszName, VMINFO_DETAILS details) +{ + if (coll.size() > 0) + { + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s\n\n", pszName); + for (size_t i = 0; i < coll.size(); ++i) + { + ComPtr<IUSBDeviceType> dev = coll[i]; + char szValue[128]; + char szNm[80]; + + SHOW_STRING_PROP(dev, Id, FmtNm(szNm, "%sActive%zu", pszPfx, i + 1), "UUID:"); + SHOW_USHORT_PROP_EX2(dev, VendorId, FmtNm(szNm, "%sVendorId%zu", pszPfx, i + 1), Info::tr("VendorId:"), "", "%#06x", "%#06x (%04X)"); + SHOW_USHORT_PROP_EX2(dev, ProductId, FmtNm(szNm, "%sProductId%zu", pszPfx, i + 1), Info::tr("ProductId:"), "", "%#06x", "%#06x (%04X)"); + + USHORT bcdRevision; + CHECK_ERROR2I_RET(dev, COMGETTER(Revision)(&bcdRevision), hrcCheck); + if (details == VMINFO_MACHINEREADABLE) + RTStrPrintf(szValue, sizeof(szValue), "%#04x%02x", bcdRevision >> 8, bcdRevision & 0xff); + else + RTStrPrintf(szValue, sizeof(szValue), "%u.%u (%02u%02u)\n", + bcdRevision >> 8, bcdRevision & 0xff, bcdRevision >> 8, bcdRevision & 0xff); + SHOW_UTF8_STRING(FmtNm(szNm, "%sRevision%zu", pszPfx, i + 1), Info::tr("Revision:"), szValue); + + SHOW_STRING_PROP_NOT_EMPTY(dev, Manufacturer, FmtNm(szNm, "%sManufacturer%zu", pszPfx, i + 1), Info::tr("Manufacturer:")); + SHOW_STRING_PROP_NOT_EMPTY(dev, Product, FmtNm(szNm, "%sProduct%zu", pszPfx, i + 1), Info::tr("Product:")); + SHOW_STRING_PROP_NOT_EMPTY(dev, SerialNumber, FmtNm(szNm, "%sSerialNumber%zu", pszPfx, i + 1), Info::tr("SerialNumber:")); + SHOW_STRING_PROP_NOT_EMPTY(dev, Address, FmtNm(szNm, "%sAddress%zu", pszPfx, i + 1), Info::tr("Address:")); + + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("\n"); + } + } + else if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s %s\n", pszName, Info::tr("<none>")); + return S_OK; +} + +/** Displays the medium attachments of the given controller. */ +static HRESULT showMediumAttachments(ComPtr<IMachine> &machine, ComPtr<IStorageController> ptrStorageCtl, VMINFO_DETAILS details) +{ + Bstr bstrStorageCtlName; + CHECK_ERROR2I_RET(ptrStorageCtl, COMGETTER(Name)(bstrStorageCtlName.asOutParam()), hrcCheck); + ULONG cDevices; + CHECK_ERROR2I_RET(ptrStorageCtl, COMGETTER(MaxDevicesPerPortCount)(&cDevices), hrcCheck); + ULONG cPorts; + CHECK_ERROR2I_RET(ptrStorageCtl, COMGETTER(PortCount)(&cPorts), hrcCheck); + + for (ULONG i = 0; i < cPorts; ++ i) + { + for (ULONG k = 0; k < cDevices; ++ k) + { + ComPtr<IMediumAttachment> mediumAttach; + HRESULT hrc = machine->GetMediumAttachment(bstrStorageCtlName.raw(), i, k, mediumAttach.asOutParam()); + if (!SUCCEEDED(hrc) && hrc != VBOX_E_OBJECT_NOT_FOUND) + { + com::GlueHandleComError(machine, "GetMediumAttachment", hrc, __FILE__, __LINE__); + return hrc; + } + + BOOL fIsEjected = FALSE; + BOOL fTempEject = FALSE; + BOOL fHotPlug = FALSE; + BOOL fNonRotational = FALSE; + BOOL fDiscard = FALSE; + DeviceType_T devType = DeviceType_Null; + if (mediumAttach) + { + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(TemporaryEject)(&fTempEject), hrcCheck); + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(IsEjected)(&fIsEjected), hrcCheck); + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(Type)(&devType), hrcCheck); + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(HotPluggable)(&fHotPlug), hrcCheck); + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(NonRotational)(&fNonRotational), hrcCheck); + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(Discard)(&fDiscard), hrcCheck); + } + + ComPtr<IMedium> medium; + hrc = machine->GetMedium(bstrStorageCtlName.raw(), i, k, medium.asOutParam()); + if (SUCCEEDED(hrc) && medium) + { + BOOL fPassthrough = FALSE; + if (mediumAttach) + { + CHECK_ERROR2I_RET(mediumAttach, COMGETTER(Passthrough)(&fPassthrough), hrcCheck); + } + + Bstr bstrFilePath; + CHECK_ERROR2I_RET(medium, COMGETTER(Location)(bstrFilePath.asOutParam()), hrcCheck); + Bstr bstrUuid; + CHECK_ERROR2I_RET(medium, COMGETTER(Id)(bstrUuid.asOutParam()), hrcCheck); + + if (details != VMINFO_MACHINEREADABLE) + RTPrintf(Info::tr(" Port %u, Unit %u: UUID: %ls%s%s%s%s%s%s\n Location: \"%ls\"\n"), + i, k, bstrUuid.raw(), + fPassthrough ? Info::tr(", passthrough enabled") : "", + fTempEject ? Info::tr(", temp eject") : "", + fIsEjected ? Info::tr(", ejected") : "", + fHotPlug ? Info::tr(", hot-pluggable") : "", + fNonRotational ? Info::tr(", non-rotational (SSD)") : "", + fDiscard ? Info::tr(", discards unused blocks") : "", + bstrFilePath.raw()); + else + { + /* Note! dvdpassthough, tempeject and IsEjected was all missed the port + and unit bits prior to VBox 7.0. */ + /** @todo This would look better on the "%ls-%d-%d-{tag}" form! */ + outputMachineReadableStringWithFmtName(&bstrFilePath, + true, "%ls-%d-%d", bstrStorageCtlName.raw(), i, k); + outputMachineReadableStringWithFmtName(&bstrUuid, + true, "%ls-ImageUUID-%d-%d", bstrStorageCtlName.raw(), i, k); + + if (fPassthrough) + outputMachineReadableStringWithFmtName("on", + true, "%ls-dvdpassthrough-%d-%d", bstrStorageCtlName.raw(), i, k); + if (devType == DeviceType_DVD) + { + outputMachineReadableStringWithFmtName(fTempEject ? "on" : "off", + true, "%ls-tempeject-%d-%d", bstrStorageCtlName.raw(), i, k); + outputMachineReadableStringWithFmtName(fIsEjected ? "on" : "off", + true, "%ls-IsEjected-%d-%d", bstrStorageCtlName.raw(), i, k); + } + + if ( bstrStorageCtlName.compare(Bstr("SATA"), Bstr::CaseInsensitive)== 0 + || bstrStorageCtlName.compare(Bstr("USB"), Bstr::CaseInsensitive)== 0) + outputMachineReadableStringWithFmtName(fHotPlug ? "on" : "off", + true, "%ls-hot-pluggable-%d-%d", bstrStorageCtlName.raw(), + i, k); + + outputMachineReadableStringWithFmtName(fNonRotational ? "on" : "off", + true, "%ls-nonrotational-%d-%d", bstrStorageCtlName.raw(), i, k); + outputMachineReadableStringWithFmtName(fDiscard ? "on" : "off", + true, "%ls-discard-%d-%d", bstrStorageCtlName.raw(), i, k); + } + } + else if (SUCCEEDED(hrc)) + { + if (details != VMINFO_MACHINEREADABLE) + RTPrintf(Info::tr(" Port %u, Unit %u: Empty%s%s\n"), i, k, + fTempEject ? Info::tr(", temp eject") : "", + fIsEjected ? Info::tr(", ejected") : ""); + else + { + outputMachineReadableStringWithFmtName("emptydrive", true, "%ls-%d-%d", bstrStorageCtlName.raw(), i, k); + if (devType == DeviceType_DVD) + outputMachineReadableStringWithFmtName(fIsEjected ? "on" : "off", + true, "%ls-IsEjected-%d-%d", bstrStorageCtlName.raw(), i, k); + } + } + else if (details == VMINFO_MACHINEREADABLE) + outputMachineReadableStringWithFmtName("none", true, "%ls-%d-%d", bstrStorageCtlName.raw(), i, k); + else if (hrc != VBOX_E_OBJECT_NOT_FOUND) + RTPrintf(Info::tr(" Port %u, Unit %u: GetMedium failed: %Rhrc\n"), i, k, hrc); + + } + } + return S_OK; +} + + +#ifdef VBOX_WITH_IOMMU_AMD +static const char *iommuTypeToString(IommuType_T iommuType, VMINFO_DETAILS details) +{ + switch (iommuType) + { + case IommuType_None: + if (details == VMINFO_MACHINEREADABLE) + return "none"; + return Info::tr("None"); + + case IommuType_Automatic: + if (details == VMINFO_MACHINEREADABLE) + return "automatic"; + return Info::tr("Automatic"); + + case IommuType_AMD: + if (details == VMINFO_MACHINEREADABLE) + return "amd"; + return "AMD"; + + case IommuType_Intel: + if (details == VMINFO_MACHINEREADABLE) + return "intel"; + return "Intel"; + + default: + if (details == VMINFO_MACHINEREADABLE) + return "unknown"; + return Info::tr("Unknown"); + } +} +#endif + +static const char *paravirtProviderToString(ParavirtProvider_T provider, VMINFO_DETAILS details) +{ + switch (provider) + { + case ParavirtProvider_None: + if (details == VMINFO_MACHINEREADABLE) + return "none"; + return Info::tr("None"); + + case ParavirtProvider_Default: + if (details == VMINFO_MACHINEREADABLE) + return "default"; + return Info::tr("Default"); + + case ParavirtProvider_Legacy: + if (details == VMINFO_MACHINEREADABLE) + return "legacy"; + return Info::tr("Legacy"); + + case ParavirtProvider_Minimal: + if (details == VMINFO_MACHINEREADABLE) + return "minimal"; + return Info::tr("Minimal"); + + case ParavirtProvider_HyperV: + if (details == VMINFO_MACHINEREADABLE) + return "hyperv"; + return "HyperV"; + + case ParavirtProvider_KVM: + if (details == VMINFO_MACHINEREADABLE) + return "kvm"; + return "KVM"; + + default: + if (details == VMINFO_MACHINEREADABLE) + return "unknown"; + return Info::tr("Unknown"); + } +} + + +/* Disable global optimizations for MSC 8.0/64 to make it compile in reasonable + time. MSC 7.1/32 doesn't have quite as much trouble with it, but still + sufficient to qualify for this hack as well since this code isn't performance + critical and probably won't gain much from the extra optimizing in real life. */ +#if defined(_MSC_VER) +# pragma optimize("g", off) +# pragma warning(push) +# if _MSC_VER < RT_MSC_VER_VC120 +# pragma warning(disable: 4748) +# endif +#endif + +HRESULT showVMInfo(ComPtr<IVirtualBox> pVirtualBox, + ComPtr<IMachine> machine, + ComPtr<ISession> pSession, + VMINFO_DETAILS details /*= VMINFO_NONE*/) +{ + HRESULT hrc; + ComPtr<IConsole> pConsole; + if (pSession) + pSession->COMGETTER(Console)(pConsole.asOutParam()); + + char szNm[80]; + char szValue[256]; + + /* + * The rules for output in -argdump format: + * 1) the key part (the [0-9a-zA-Z_\-]+ string before the '=' delimiter) + * is all lowercase for "VBoxManage modifyvm" parameters. Any + * other values printed are in CamelCase. + * 2) strings (anything non-decimal) are printed surrounded by + * double quotes '"'. If the strings themselves contain double + * quotes, these characters are escaped by '\'. Any '\' character + * in the original string is also escaped by '\'. + * 3) numbers (containing just [0-9\-]) are written out unchanged. + */ + + BOOL fAccessible; + CHECK_ERROR2I_RET(machine, COMGETTER(Accessible)(&fAccessible), hrcCheck); + if (!fAccessible) + { + Bstr uuid; + machine->COMGETTER(Id)(uuid.asOutParam()); + if (details == VMINFO_COMPACT) + RTPrintf(Info::tr("\"<inaccessible>\" {%s}\n"), Utf8Str(uuid).c_str()); + else + { + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("name=\"<inaccessible>\"\n"); + else + RTPrintf(Info::tr("Name: <inaccessible!>\n")); + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("UUID=\"%s\"\n", Utf8Str(uuid).c_str()); + else + RTPrintf("UUID: %s\n", Utf8Str(uuid).c_str()); + if (details != VMINFO_MACHINEREADABLE) + { + Bstr settingsFilePath; + hrc = machine->COMGETTER(SettingsFilePath)(settingsFilePath.asOutParam()); + RTPrintf(Info::tr("Config file: %ls\n"), settingsFilePath.raw()); + + Bstr strCipher; + Bstr strPasswordId; + HRESULT hrc2 = machine->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam()); + if (SUCCEEDED(hrc2)) + { + RTPrintf("Encryption: enabled\n"); + RTPrintf("Cipher: %ls\n", strCipher.raw()); + RTPrintf("Password ID: %ls\n", strPasswordId.raw()); + } + else + RTPrintf("Encryption: disabled\n"); + + ComPtr<IVirtualBoxErrorInfo> accessError; + hrc = machine->COMGETTER(AccessError)(accessError.asOutParam()); + RTPrintf(Info::tr("Access error details:\n")); + ErrorInfo ei(accessError); + GluePrintErrorInfo(ei); + RTPrintf("\n"); + } + } + return S_OK; + } + + if (details == VMINFO_COMPACT) + { + Bstr machineName; + machine->COMGETTER(Name)(machineName.asOutParam()); + Bstr uuid; + machine->COMGETTER(Id)(uuid.asOutParam()); + + RTPrintf("\"%ls\" {%s}\n", machineName.raw(), Utf8Str(uuid).c_str()); + return S_OK; + } + + SHOW_STRING_PROP( machine, Name, "name", Info::tr("Name:")); + { + Bstr strCipher; + Bstr strPasswordId; + HRESULT hrc2 = machine->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam()); + if (SUCCEEDED(hrc2)) + { + RTPrintf("Encryption: enabled\n"); + RTPrintf("Cipher: %ls\n", strCipher.raw()); + RTPrintf("Password ID: %ls\n", strPasswordId.raw()); + } + else + RTPrintf("Encryption: disabled\n"); + } + SHOW_STRINGARRAY_PROP( machine, Groups, "groups", Info::tr("Groups:")); + Bstr osTypeId; + CHECK_ERROR2I_RET(machine, COMGETTER(OSTypeId)(osTypeId.asOutParam()), hrcCheck); + ComPtr<IGuestOSType> osType; + pVirtualBox->GetGuestOSType(osTypeId.raw(), osType.asOutParam()); + if (!osType.isNull()) + SHOW_STRING_PROP( osType, Description, "ostype", Info::tr("Guest OS:")); + else + SHOW_STRING_PROP( machine, OSTypeId, "ostype", Info::tr("Guest OS:")); + SHOW_UUID_PROP( machine, Id, "UUID", "UUID:"); + SHOW_STRING_PROP( machine, SettingsFilePath, "CfgFile", Info::tr("Config file:")); + SHOW_STRING_PROP( machine, SnapshotFolder, "SnapFldr", Info::tr("Snapshot folder:")); + SHOW_STRING_PROP( machine, LogFolder, "LogFldr", Info::tr("Log folder:")); + SHOW_UUID_PROP( machine, HardwareUUID, "hardwareuuid", Info::tr("Hardware UUID:")); + SHOW_ULONG_PROP( machine, MemorySize, "memory", Info::tr("Memory size:"), "MB"); + SHOW_BOOLEAN_PROP( machine, PageFusionEnabled, "pagefusion", Info::tr("Page Fusion:")); + ComPtr<IGraphicsAdapter> pGraphicsAdapter; + machine->COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam()); + SHOW_ULONG_PROP(pGraphicsAdapter, VRAMSize, "vram", Info::tr("VRAM size:"), "MB"); + SHOW_ULONG_PROP( machine, CPUExecutionCap, "cpuexecutioncap", Info::tr("CPU exec cap:"), "%"); + SHOW_BOOLEAN_PROP( machine, HPETEnabled, "hpet", Info::tr("HPET:")); + SHOW_STRING_PROP_MAJ( machine, CPUProfile, "cpu-profile", Info::tr("CPUProfile:"), "host", 6); + + ChipsetType_T chipsetType; + CHECK_ERROR2I_RET(machine, COMGETTER(ChipsetType)(&chipsetType), hrcCheck); + const char *pszChipsetType; + switch (chipsetType) + { + case ChipsetType_Null: + if (details == VMINFO_MACHINEREADABLE) + pszChipsetType = "invalid"; + else + pszChipsetType = Info::tr("invalid"); + break; + case ChipsetType_PIIX3: pszChipsetType = "piix3"; break; + case ChipsetType_ICH9: pszChipsetType = "ich9"; break; + default: + AssertFailed(); + if (details == VMINFO_MACHINEREADABLE) + pszChipsetType = "unknown"; + else + pszChipsetType = Info::tr("unknown"); + break; + } + SHOW_UTF8_STRING("chipset", Info::tr("Chipset:"), pszChipsetType); + + FirmwareType_T firmwareType; + CHECK_ERROR2I_RET(machine, COMGETTER(FirmwareType)(&firmwareType), hrcCheck); + const char *pszFirmwareType; + switch (firmwareType) + { + case FirmwareType_BIOS: pszFirmwareType = "BIOS"; break; + case FirmwareType_EFI: pszFirmwareType = "EFI"; break; + case FirmwareType_EFI32: pszFirmwareType = "EFI32"; break; + case FirmwareType_EFI64: pszFirmwareType = "EFI64"; break; + case FirmwareType_EFIDUAL: pszFirmwareType = "EFIDUAL"; break; + default: + AssertFailed(); + if (details == VMINFO_MACHINEREADABLE) + pszFirmwareType = "unknown"; + else + pszFirmwareType = Info::tr("unknown"); + break; + } + SHOW_UTF8_STRING("firmware", Info::tr("Firmware:"), pszFirmwareType); + + SHOW_ULONG_PROP( machine, CPUCount, "cpus", Info::tr("Number of CPUs:"), ""); + SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_PAE, &f), "pae", "PAE:"); + SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_LongMode, &f), "longmode", Info::tr("Long Mode:")); + SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_TripleFaultReset, &f), "triplefaultreset", Info::tr("Triple Fault Reset:")); + SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_APIC, &f), "apic", "APIC:"); + SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_X2APIC, &f), "x2apic", "X2APIC:"); + SHOW_BOOLEAN_METHOD( machine, GetCPUProperty(CPUPropertyType_HWVirt, &f), "nested-hw-virt", Info::tr("Nested VT-x/AMD-V:")); + SHOW_ULONG_PROP( machine, CPUIDPortabilityLevel, "cpuid-portability-level", Info::tr("CPUID Portability Level:"), ""); + + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s ", Info::tr("CPUID overrides:")); + ULONG uOrdinal = 0; + for (uOrdinal = 0; uOrdinal < _4K; uOrdinal++) + { + ULONG uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX; + hrc = machine->GetCPUIDLeafByOrdinal(uOrdinal, &uLeaf, &uSubLeaf, &uEAX, &uEBX, &uECX, &uEDX); + if (SUCCEEDED(hrc)) + { + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("cpuid=%08x,%08x,%08x,%08x,%08x,%08x", uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX); + else + { + if (!uOrdinal) + RTPrintf(Info::tr("Leaf no. EAX EBX ECX EDX\n")); + RTPrintf("%-28s %08x/%03x %08x %08x %08x %08x\n", "", uLeaf, uSubLeaf, uEAX, uEBX, uECX, uEDX); + } + } + else + { + if (hrc != E_INVALIDARG) + com::GlueHandleComError(machine, "GetCPUIDLeaf", hrc, __FILE__, __LINE__); + break; + } + } + if (!uOrdinal && details != VMINFO_MACHINEREADABLE) + RTPrintf(Info::tr("None\n")); + + ComPtr<IBIOSSettings> biosSettings; + CHECK_ERROR2I_RET(machine, COMGETTER(BIOSSettings)(biosSettings.asOutParam()), hrcCheck); + + ComPtr<INvramStore> nvramStore; + CHECK_ERROR2I_RET(machine, COMGETTER(NonVolatileStore)(nvramStore.asOutParam()), hrcCheck); + + BIOSBootMenuMode_T bootMenuMode; + CHECK_ERROR2I_RET(biosSettings, COMGETTER(BootMenuMode)(&bootMenuMode), hrcCheck); + const char *pszBootMenu; + switch (bootMenuMode) + { + case BIOSBootMenuMode_Disabled: + if (details == VMINFO_MACHINEREADABLE) + pszBootMenu = "disabled"; + else + pszBootMenu = Info::tr("disabled"); + break; + case BIOSBootMenuMode_MenuOnly: + if (details == VMINFO_MACHINEREADABLE) + pszBootMenu = "menuonly"; + else + pszBootMenu = Info::tr("menu only"); + break; + default: + if (details == VMINFO_MACHINEREADABLE) + pszBootMenu = "messageandmenu"; + else + pszBootMenu = Info::tr("message and menu"); + } + SHOW_UTF8_STRING("bootmenu", Info::tr("Boot menu mode:"), pszBootMenu); + + ComPtr<ISystemProperties> systemProperties; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), hrcCheck); + ULONG maxBootPosition = 0; + CHECK_ERROR2I_RET(systemProperties, COMGETTER(MaxBootPosition)(&maxBootPosition), hrcCheck); + for (ULONG i = 1; i <= maxBootPosition; i++) + { + DeviceType_T bootOrder; + CHECK_ERROR2I_RET(machine, GetBootOrder(i, &bootOrder), hrcCheck); + const char *pszDevice; + if (bootOrder == DeviceType_Floppy) + pszDevice = details == VMINFO_MACHINEREADABLE ? "floppy" : Info::tr("Floppy"); + else if (bootOrder == DeviceType_DVD) + pszDevice = details == VMINFO_MACHINEREADABLE ? "dvd" : "DVD"; + else if (bootOrder == DeviceType_HardDisk) + pszDevice = details == VMINFO_MACHINEREADABLE ? "disk" : Info::tr("HardDisk"); + else if (bootOrder == DeviceType_Network) + pszDevice = details == VMINFO_MACHINEREADABLE ? "net" : Info::tr("Network"); + else if (bootOrder == DeviceType_USB) + pszDevice = details == VMINFO_MACHINEREADABLE ? "usb" : "USB"; + else if (bootOrder == DeviceType_SharedFolder) + pszDevice = details == VMINFO_MACHINEREADABLE ? "sharedfolder" : Info::tr("Shared Folder"); + else + pszDevice = details == VMINFO_MACHINEREADABLE ? "none" : Info::tr("Not Assigned"); + SHOW_UTF8_STRING(FmtNm(szNm, "boot%u", i), FmtNm(szNm, Info::tr("Boot Device %u:"), i), pszDevice); + } + + SHOW_BOOLEAN_PROP(biosSettings, ACPIEnabled, "acpi", "ACPI:"); + SHOW_BOOLEAN_PROP(biosSettings, IOAPICEnabled, "ioapic", "IOAPIC:"); + + APICMode_T apicMode; + CHECK_ERROR2I_RET(biosSettings, COMGETTER(APICMode)(&apicMode), hrcCheck); + const char *pszAPIC; + switch (apicMode) + { + case APICMode_Disabled: + if (details == VMINFO_MACHINEREADABLE) + pszAPIC = "disabled"; + else + pszAPIC = Info::tr("disabled"); + break; + case APICMode_APIC: + default: + if (details == VMINFO_MACHINEREADABLE) + pszAPIC = "apic"; + else + pszAPIC = "APIC"; + break; + case APICMode_X2APIC: + if (details == VMINFO_MACHINEREADABLE) + pszAPIC = "x2apic"; + else + pszAPIC = "x2APIC"; + break; + } + SHOW_UTF8_STRING("biosapic", Info::tr("BIOS APIC mode:"), pszAPIC); + + SHOW_LONG64_PROP(biosSettings, TimeOffset, "biossystemtimeoffset", Info::tr("Time offset:"), Info::tr("ms")); + Bstr bstrNVRAMFile; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(NonVolatileStorageFile)(bstrNVRAMFile.asOutParam()), hrcCheck); + if (bstrNVRAMFile.isNotEmpty()) + SHOW_BSTR_STRING("BIOS NVRAM File", Info::tr("BIOS NVRAM File:"), bstrNVRAMFile); + SHOW_BOOLEAN_PROP_EX(machine, RTCUseUTC, "rtcuseutc", Info::tr("RTC:"), "UTC", Info::tr("local time")); + SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &f), "hwvirtex", Info::tr("Hardware Virtualization:")); + SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &f),"nestedpaging", Info::tr("Nested Paging:")); + SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &f), "largepages", Info::tr("Large Pages:")); + SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_VPID, &f), "vtxvpid", "VT-x VPID:"); + SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_UnrestrictedExecution, &f), "vtxux", Info::tr("VT-x Unrestricted Exec.:")); + SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_VirtVmsaveVmload, &f), "virtvmsavevmload", Info::tr("AMD-V Virt. Vmsave/Vmload:")); + +#ifdef VBOX_WITH_IOMMU_AMD + IommuType_T iommuType; + CHECK_ERROR2I_RET(machine, COMGETTER(IommuType)(&iommuType), hrcCheck); + const char *pszIommuType = iommuTypeToString(iommuType, details); + SHOW_UTF8_STRING("iommu", "IOMMU:", pszIommuType); +#endif + + ParavirtProvider_T paravirtProvider; + CHECK_ERROR2I_RET(machine, COMGETTER(ParavirtProvider)(¶virtProvider), hrcCheck); + const char *pszParavirtProvider = paravirtProviderToString(paravirtProvider, details); + SHOW_UTF8_STRING("paravirtprovider", Info::tr("Paravirt. Provider:"), pszParavirtProvider); + + ParavirtProvider_T effParavirtProvider; + CHECK_ERROR2I_RET(machine, GetEffectiveParavirtProvider(&effParavirtProvider), hrcCheck); + const char *pszEffParavirtProvider = paravirtProviderToString(effParavirtProvider, details); + SHOW_UTF8_STRING("effparavirtprovider", Info::tr("Effective Paravirt. Prov.:"), pszEffParavirtProvider); + + Bstr paravirtDebug; + CHECK_ERROR2I_RET(machine, COMGETTER(ParavirtDebug)(paravirtDebug.asOutParam()), hrcCheck); + if (paravirtDebug.isNotEmpty()) + SHOW_BSTR_STRING("paravirtdebug", Info::tr("Paravirt. Debug:"), paravirtDebug); + + MachineState_T machineState; + CHECK_ERROR2I_RET(machine, COMGETTER(State)(&machineState), hrcCheck); + const char *pszState = machineStateToName(machineState, details == VMINFO_MACHINEREADABLE /*=fShort*/); + + LONG64 stateSince; + machine->COMGETTER(LastStateChange)(&stateSince); + RTTIMESPEC timeSpec; + RTTimeSpecSetMilli(&timeSpec, stateSince); + char pszTime[30] = {0}; + RTTimeSpecToString(&timeSpec, pszTime, sizeof(pszTime)); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("VMState=\"%s\"\n", pszState); + RTPrintf("VMStateChangeTime=\"%s\"\n", pszTime); + + Bstr stateFile; + machine->COMGETTER(StateFilePath)(stateFile.asOutParam()); + if (!stateFile.isEmpty()) + RTPrintf("VMStateFile=\"%ls\"\n", stateFile.raw()); + } + else + RTPrintf(Info::tr("%-28s %s (since %s)\n"), Info::tr("State:"), pszState, pszTime); + + GraphicsControllerType_T enmGraphics; + hrc = pGraphicsAdapter->COMGETTER(GraphicsControllerType)(&enmGraphics); + if (SUCCEEDED(hrc)) + { + const char *pszCtrl; + switch (enmGraphics) + { + case GraphicsControllerType_Null: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "null"; + else + pszCtrl = Info::tr("Null"); + break; + case GraphicsControllerType_VBoxVGA: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "vboxvga"; + else + pszCtrl = "VBoxVGA"; + break; + case GraphicsControllerType_VMSVGA: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "vmsvga"; + else + pszCtrl = "VMSVGA"; + break; + case GraphicsControllerType_VBoxSVGA: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "vboxsvga"; + else + pszCtrl = "VBoxSVGA"; + break; + default: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "unknown"; + else + pszCtrl = Info::tr("Unknown"); + break; + } + + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("graphicscontroller=\"%s\"\n", pszCtrl); + else + RTPrintf("%-28s %s\n", Info::tr("Graphics Controller:"), pszCtrl); + } + + SHOW_ULONG_PROP(pGraphicsAdapter, MonitorCount, "monitorcount", Info::tr("Monitor count:"), ""); + SHOW_BOOLEAN_PROP(pGraphicsAdapter, Accelerate3DEnabled, "accelerate3d", Info::tr("3D Acceleration:")); +#ifdef VBOX_WITH_VIDEOHWACCEL + SHOW_BOOLEAN_PROP(pGraphicsAdapter, Accelerate2DVideoEnabled, "accelerate2dvideo", Info::tr("2D Video Acceleration:")); +#endif + SHOW_BOOLEAN_PROP( machine, TeleporterEnabled, "teleporterenabled", Info::tr("Teleporter Enabled:")); + SHOW_ULONG_PROP( machine, TeleporterPort, "teleporterport", Info::tr("Teleporter Port:"), ""); + SHOW_STRING_PROP( machine, TeleporterAddress, "teleporteraddress", Info::tr("Teleporter Address:")); + SHOW_STRING_PROP( machine, TeleporterPassword, "teleporterpassword", Info::tr("Teleporter Password:")); + SHOW_BOOLEAN_PROP( machine, TracingEnabled, "tracing-enabled", Info::tr("Tracing Enabled:")); + SHOW_BOOLEAN_PROP( machine, AllowTracingToAccessVM, "tracing-allow-vm-access", Info::tr("Allow Tracing to Access VM:")); + SHOW_STRING_PROP( machine, TracingConfig, "tracing-config", Info::tr("Tracing Configuration:")); + SHOW_BOOLEAN_PROP( machine, AutostartEnabled, "autostart-enabled", Info::tr("Autostart Enabled:")); + SHOW_ULONG_PROP( machine, AutostartDelay, "autostart-delay", Info::tr("Autostart Delay:"), ""); + SHOW_STRING_PROP( machine, DefaultFrontend, "defaultfrontend", Info::tr("Default Frontend:")); + + VMProcPriority_T enmVMProcPriority; + CHECK_ERROR2I_RET(machine, COMGETTER(VMProcessPriority)(&enmVMProcPriority), hrcCheck); + const char *pszVMProcPriority; + switch (enmVMProcPriority) + { + case VMProcPriority_Flat: + if (details == VMINFO_MACHINEREADABLE) + pszVMProcPriority = "flat"; + else + pszVMProcPriority = Info::tr("flat"); + break; + case VMProcPriority_Low: + if (details == VMINFO_MACHINEREADABLE) + pszVMProcPriority = "low"; + else + pszVMProcPriority = Info::tr("low"); + break; + case VMProcPriority_Normal: + if (details == VMINFO_MACHINEREADABLE) + pszVMProcPriority = "normal"; + else + pszVMProcPriority = Info::tr("normal"); + break; + case VMProcPriority_High: + if (details == VMINFO_MACHINEREADABLE) + pszVMProcPriority = "high"; + else + pszVMProcPriority = Info::tr("high"); + break; + default: + if (details == VMINFO_MACHINEREADABLE) + pszVMProcPriority = "default"; + else + pszVMProcPriority = Info::tr("default"); + break; + } + SHOW_UTF8_STRING("vmprocpriority", Info::tr("VM process priority:"), pszVMProcPriority); + +/** @todo Convert the remainder of the function to SHOW_XXX macros and add error + * checking where missing. */ + /* + * Storage Controllers and their attached Mediums. + */ + com::SafeIfaceArray<IStorageController> storageCtls; + CHECK_ERROR(machine, COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(storageCtls))); + if (storageCtls.size() > 0) + { + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%s\n", Info::tr("Storage Controllers:")); + + for (size_t i = 0; i < storageCtls.size(); ++i) + { + ComPtr<IStorageController> storageCtl = storageCtls[i]; + + Bstr bstrName; + CHECK_ERROR2I_RET(storageCtl, COMGETTER(Name)(bstrName.asOutParam()), hrcCheck); + StorageControllerType_T enmCtlType = StorageControllerType_Null; + CHECK_ERROR2I_RET(storageCtl, COMGETTER(ControllerType)(&enmCtlType), hrcCheck); + ULONG uInstance = 0; + CHECK_ERROR2I_RET(storageCtl, COMGETTER(Instance)(&uInstance), hrcCheck); + ULONG cMaxPorts = 0; + CHECK_ERROR2I_RET(storageCtl, COMGETTER(MaxPortCount)(&cMaxPorts), hrcCheck); + ULONG cPorts = 0; + CHECK_ERROR2I_RET(storageCtl, COMGETTER(PortCount)(&cPorts), hrcCheck); + BOOL fBootable = FALSE; + CHECK_ERROR2I_RET(storageCtl, COMGETTER(Bootable)(&fBootable), hrcCheck); + if (details == VMINFO_MACHINEREADABLE) + { + outputMachineReadableString(FmtNm(szNm, "storagecontrollername%u", i), &bstrName); + outputMachineReadableString(FmtNm(szNm, "storagecontrollertype%u", i), + storageControllerTypeToName(enmCtlType, true)); + RTPrintf("storagecontrollerinstance%u=\"%u\"\n", i, uInstance); + RTPrintf("storagecontrollermaxportcount%u=\"%u\"\n", i, cMaxPorts); + RTPrintf("storagecontrollerportcount%u=\"%u\"\n", i, cPorts); + RTPrintf("storagecontrollerbootable%u=\"%s\"\n", i, fBootable ? "on" : "off"); + } + else + { + RTPrintf(Info::tr("#%u: '%ls', Type: %s, Instance: %u, Ports: %u (max %u), %s\n"), i, bstrName.raw(), + storageControllerTypeToName(enmCtlType, false), uInstance, cPorts, cMaxPorts, + fBootable ? Info::tr("Bootable") : Info::tr("Not bootable")); + hrc = showMediumAttachments(machine, storageCtl, details); + if (FAILED(hrc)) + return hrc; + } + } + } + else if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s %s\n", Info::tr("Storage Controllers:"), Info::tr("<none>")); + + if (details == VMINFO_MACHINEREADABLE) + for (size_t j = 0; j < storageCtls.size(); ++ j) + { + hrc = showMediumAttachments(machine, storageCtls[j], details); + if (FAILED(hrc)) + return hrc; + } + + /* get the maximum amount of NICS */ + ULONG maxNICs = getMaxNics(pVirtualBox, machine); + + for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++) + { + ComPtr<INetworkAdapter> nic; + hrc = machine->GetNetworkAdapter(currentNIC, nic.asOutParam()); + if (SUCCEEDED(hrc) && nic) + { + FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "nic%u" : Info::tr("NIC %u:"), currentNIC + 1); + + BOOL fEnabled; + nic->COMGETTER(Enabled)(&fEnabled); + if (!fEnabled) + { + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("%s=\"none\"\n", szNm); + else + RTPrintf(Info::tr("%-28s disabled\n"), szNm); + } + else + { + Bstr strMACAddress; + nic->COMGETTER(MACAddress)(strMACAddress.asOutParam()); + Utf8Str strAttachment; + Utf8Str strNatSettings; + Utf8Str strNatForwardings; + NetworkAttachmentType_T attachment; + nic->COMGETTER(AttachmentType)(&attachment); + switch (attachment) + { + case NetworkAttachmentType_Null: + if (details == VMINFO_MACHINEREADABLE) + strAttachment = "null"; + else + strAttachment = Info::tr("none"); + break; + + case NetworkAttachmentType_NAT: + { + Bstr strNetwork; + ComPtr<INATEngine> engine; + nic->COMGETTER(NATEngine)(engine.asOutParam()); + engine->COMGETTER(Network)(strNetwork.asOutParam()); + com::SafeArray<BSTR> forwardings; + engine->COMGETTER(Redirects)(ComSafeArrayAsOutParam(forwardings)); + strNatForwardings = ""; + for (size_t i = 0; i < forwardings.size(); ++i) + { + bool fSkip = false; + BSTR r = forwardings[i]; + Utf8Str utf = Utf8Str(r); + Utf8Str strName; + Utf8Str strProto; + Utf8Str strHostPort; + Utf8Str strHostIP; + Utf8Str strGuestPort; + Utf8Str strGuestIP; + size_t pos, ppos; + pos = ppos = 0; +#define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \ + do { \ + pos = str.find(",", ppos); \ + if (pos == Utf8Str::npos) \ + { \ + Log(( #res " extracting from %s is failed\n", str.c_str())); \ + fSkip = true; \ + } \ + res = str.substr(ppos, pos - ppos); \ + Log2((#res " %s pos:%d, ppos:%d\n", res.c_str(), pos, ppos)); \ + ppos = pos + 1; \ + } while (0) + ITERATE_TO_NEXT_TERM(strName, utf, pos, ppos); + if (fSkip) continue; + ITERATE_TO_NEXT_TERM(strProto, utf, pos, ppos); + if (fSkip) continue; + ITERATE_TO_NEXT_TERM(strHostIP, utf, pos, ppos); + if (fSkip) continue; + ITERATE_TO_NEXT_TERM(strHostPort, utf, pos, ppos); + if (fSkip) continue; + ITERATE_TO_NEXT_TERM(strGuestIP, utf, pos, ppos); + if (fSkip) continue; + strGuestPort = utf.substr(ppos, utf.length() - ppos); +#undef ITERATE_TO_NEXT_TERM + switch (strProto.toUInt32()) + { + case NATProtocol_TCP: + strProto = "tcp"; + break; + case NATProtocol_UDP: + strProto = "udp"; + break; + default: + strProto = "unk"; + break; + } + if (details == VMINFO_MACHINEREADABLE) + /** @todo r=bird: This probably isn't good enough wrt escaping. */ + strNatForwardings.appendPrintf("Forwarding(%d)=\"%s,%s,%s,%s,%s,%s\"\n", + i, strName.c_str(), strProto.c_str(), + strHostIP.c_str(), strHostPort.c_str(), + strGuestIP.c_str(), strGuestPort.c_str()); + else + strNatForwardings.appendPrintf(Info::tr("NIC %d Rule(%d): name = %s, protocol = %s, host ip = %s, host port = %s, guest ip = %s, guest port = %s\n"), + currentNIC + 1, i, strName.c_str(), + strProto.c_str(), strHostIP.c_str(), strHostPort.c_str(), + strGuestIP.c_str(), strGuestPort.c_str()); + } + ULONG mtu = 0; + ULONG sockSnd = 0; + ULONG sockRcv = 0; + ULONG tcpSnd = 0; + ULONG tcpRcv = 0; + engine->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv); + +/** @todo r=klaus dnsproxy etc needs to be dumped, too */ + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("natnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.length() ? strNetwork.raw(): Bstr("nat").raw()); + strAttachment = "nat"; + strNatSettings.printf("mtu=\"%d\"\nsockSnd=\"%d\"\nsockRcv=\"%d\"\ntcpWndSnd=\"%d\"\ntcpWndRcv=\"%d\"\n", + mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64); + } + else + { + strAttachment = "NAT"; + strNatSettings.printf(Info::tr("NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d)\n"), + currentNIC + 1, mtu, sockSnd ? sockSnd : 64, sockRcv ? sockRcv : 64, tcpSnd ? tcpSnd : 64, tcpRcv ? tcpRcv : 64); + } + break; + } + + case NetworkAttachmentType_Bridged: + { + Bstr strBridgeAdp; + nic->COMGETTER(BridgedInterface)(strBridgeAdp.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("bridgeadapter%d=\"%ls\"\n", currentNIC + 1, strBridgeAdp.raw()); + strAttachment = "bridged"; + } + else + strAttachment.printf(Info::tr("Bridged Interface '%ls'"), strBridgeAdp.raw()); + break; + } + + case NetworkAttachmentType_Internal: + { + Bstr strNetwork; + nic->COMGETTER(InternalNetwork)(strNetwork.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("intnet%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw()); + strAttachment = "intnet"; + } + else + strAttachment.printf(Info::tr("Internal Network '%s'"), Utf8Str(strNetwork).c_str()); + break; + } + + case NetworkAttachmentType_HostOnly: + { + Bstr strHostonlyAdp; + nic->COMGETTER(HostOnlyInterface)(strHostonlyAdp.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("hostonlyadapter%d=\"%ls\"\n", currentNIC + 1, strHostonlyAdp.raw()); + strAttachment = "hostonly"; + } + else + strAttachment.printf(Info::tr("Host-only Interface '%ls'"), strHostonlyAdp.raw()); + break; + } + + case NetworkAttachmentType_Generic: + { + Bstr strGenericDriver; + nic->COMGETTER(GenericDriver)(strGenericDriver.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("generic%d=\"%ls\"\n", currentNIC + 1, strGenericDriver.raw()); + strAttachment = "Generic"; + } + else + { + strAttachment.printf(Info::tr("Generic '%ls'"), strGenericDriver.raw()); + + // show the generic properties + com::SafeArray<BSTR> aProperties; + com::SafeArray<BSTR> aValues; + hrc = nic->GetProperties(NULL, + ComSafeArrayAsOutParam(aProperties), + ComSafeArrayAsOutParam(aValues)); + if (SUCCEEDED(hrc)) + { + strAttachment += " { "; + for (unsigned i = 0; i < aProperties.size(); ++i) + strAttachment.appendPrintf(!i ? "%ls='%ls'" : ", %ls='%ls'", aProperties[i], aValues[i]); + strAttachment += " }"; + } + } + break; + } + + case NetworkAttachmentType_NATNetwork: + { + Bstr strNetwork; + nic->COMGETTER(NATNetwork)(strNetwork.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("nat-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw()); + strAttachment = "natnetwork"; + } + else + strAttachment.printf(Info::tr("NAT Network '%s'"), Utf8Str(strNetwork).c_str()); + break; + } + +#ifdef VBOX_WITH_VMNET + case NetworkAttachmentType_HostOnlyNetwork: + { + Bstr strNetwork; + nic->COMGETTER(HostOnlyNetwork)(strNetwork.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("hostonly-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw()); + strAttachment = "hostonlynetwork"; + } + else + strAttachment.printf(Info::tr("Host Only Network '%s'"), Utf8Str(strNetwork).c_str()); + break; + } +#endif /* VBOX_WITH_VMNET */ + +#ifdef VBOX_WITH_CLOUD_NET + case NetworkAttachmentType_Cloud: + { + Bstr strNetwork; + nic->COMGETTER(CloudNetwork)(strNetwork.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("cloud-network%d=\"%ls\"\n", currentNIC + 1, strNetwork.raw()); + strAttachment = "cloudnetwork"; + } + else + strAttachment.printf(Info::tr("Cloud Network '%s'"), Utf8Str(strNetwork).c_str()); + break; + } +#endif /* VBOX_WITH_CLOUD_NET */ + + default: + if (details == VMINFO_MACHINEREADABLE) + strAttachment = "unknown"; + else + strAttachment = Info::tr("unknown"); + break; + } + + /* cable connected */ + BOOL fConnected; + nic->COMGETTER(CableConnected)(&fConnected); + + /* promisc policy */ + NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy; + CHECK_ERROR2I_RET(nic, COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy), hrcCheck); + const char *pszPromiscuousGuestPolicy; + switch (enmPromiscModePolicy) + { + case NetworkAdapterPromiscModePolicy_Deny: pszPromiscuousGuestPolicy = Info::tr("deny"); break; + case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = Info::tr("allow-vms"); break; + case NetworkAdapterPromiscModePolicy_AllowAll: pszPromiscuousGuestPolicy = Info::tr("allow-all"); break; + default: AssertFailedReturn(E_INVALIDARG); + } + + /* trace stuff */ + BOOL fTraceEnabled; + nic->COMGETTER(TraceEnabled)(&fTraceEnabled); + Bstr traceFile; + nic->COMGETTER(TraceFile)(traceFile.asOutParam()); + + /* NIC type */ + NetworkAdapterType_T NICType; + nic->COMGETTER(AdapterType)(&NICType); + const char *pszNICType; + switch (NICType) + { + case NetworkAdapterType_Am79C970A: pszNICType = "Am79C970A"; break; + case NetworkAdapterType_Am79C973: pszNICType = "Am79C973"; break; + case NetworkAdapterType_Am79C960: pszNICType = "Am79C960"; break; +#ifdef VBOX_WITH_E1000 + case NetworkAdapterType_I82540EM: pszNICType = "82540EM"; break; + case NetworkAdapterType_I82543GC: pszNICType = "82543GC"; break; + case NetworkAdapterType_I82545EM: pszNICType = "82545EM"; break; +#endif +#ifdef VBOX_WITH_VIRTIO + case NetworkAdapterType_Virtio: pszNICType = "virtio"; break; +#endif + case NetworkAdapterType_NE1000: pszNICType = "NE1000"; break; + case NetworkAdapterType_NE2000: pszNICType = "NE2000"; break; + case NetworkAdapterType_WD8003: pszNICType = "WD8003"; break; + case NetworkAdapterType_WD8013: pszNICType = "WD8013"; break; + case NetworkAdapterType_ELNK2: pszNICType = "3C503"; break; + case NetworkAdapterType_ELNK1: pszNICType = "3C501"; break; + default: + AssertFailed(); + if (details == VMINFO_MACHINEREADABLE) + pszNICType = "unknown"; + else + pszNICType = Info::tr("unknown"); + break; + } + + /* reported line speed */ + ULONG ulLineSpeed; + nic->COMGETTER(LineSpeed)(&ulLineSpeed); + + /* boot priority of the adapter */ + ULONG ulBootPriority; + nic->COMGETTER(BootPriority)(&ulBootPriority); + + /* bandwidth group */ + ComObjPtr<IBandwidthGroup> pBwGroup; + Bstr strBwGroup; + nic->COMGETTER(BandwidthGroup)(pBwGroup.asOutParam()); + if (!pBwGroup.isNull()) + pBwGroup->COMGETTER(Name)(strBwGroup.asOutParam()); + + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("macaddress%d=\"%ls\"\n", currentNIC + 1, strMACAddress.raw()); + RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off"); + RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.c_str()); + RTPrintf("nictype%d=\"%s\"\n", currentNIC + 1, pszNICType); + RTPrintf("nicspeed%d=\"%d\"\n", currentNIC + 1, ulLineSpeed); + } + else + RTPrintf(Info::tr("%-28s MAC: %ls, Attachment: %s, Cable connected: %s, Trace: %s (file: %ls), Type: %s, Reported speed: %d Mbps, Boot priority: %d, Promisc Policy: %s, Bandwidth group: %ls\n"), + szNm, strMACAddress.raw(), strAttachment.c_str(), + fConnected ? Info::tr("on") : Info::tr("off"), + fTraceEnabled ? Info::tr("on") : Info::tr("off"), + traceFile.isEmpty() ? Bstr(Info::tr("none")).raw() : traceFile.raw(), + pszNICType, + ulLineSpeed / 1000, + (int)ulBootPriority, + pszPromiscuousGuestPolicy, + strBwGroup.isEmpty() ? Bstr(Info::tr("none")).raw() : strBwGroup.raw()); + if (strNatSettings.length()) + RTPrintf(strNatSettings.c_str()); + if (strNatForwardings.length()) + RTPrintf(strNatForwardings.c_str()); + } + } + } + + /* Pointing device information */ + PointingHIDType_T aPointingHID; + const char *pszHID = Info::tr("Unknown"); + const char *pszMrHID = "unknown"; + machine->COMGETTER(PointingHIDType)(&aPointingHID); + switch (aPointingHID) + { + case PointingHIDType_None: + pszHID = Info::tr("None"); + pszMrHID = "none"; + break; + case PointingHIDType_PS2Mouse: + pszHID = Info::tr("PS/2 Mouse"); + pszMrHID = "ps2mouse"; + break; + case PointingHIDType_USBMouse: + pszHID = Info::tr("USB Mouse"); + pszMrHID = "usbmouse"; + break; + case PointingHIDType_USBTablet: + pszHID = Info::tr("USB Tablet"); + pszMrHID = "usbtablet"; + break; + case PointingHIDType_ComboMouse: + pszHID = Info::tr("USB Tablet and PS/2 Mouse"); + pszMrHID = "combomouse"; + break; + case PointingHIDType_USBMultiTouch: + pszHID = Info::tr("USB Multi-Touch"); + pszMrHID = "usbmultitouch"; + break; + default: + break; + } + SHOW_UTF8_STRING("hidpointing", Info::tr("Pointing Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID); + + /* Keyboard device information */ + KeyboardHIDType_T aKeyboardHID; + machine->COMGETTER(KeyboardHIDType)(&aKeyboardHID); + pszHID = Info::tr("Unknown"); + pszMrHID = "unknown"; + switch (aKeyboardHID) + { + case KeyboardHIDType_None: + pszHID = Info::tr("None"); + pszMrHID = "none"; + break; + case KeyboardHIDType_PS2Keyboard: + pszHID = Info::tr("PS/2 Keyboard"); + pszMrHID = "ps2kbd"; + break; + case KeyboardHIDType_USBKeyboard: + pszHID = Info::tr("USB Keyboard"); + pszMrHID = "usbkbd"; + break; + case KeyboardHIDType_ComboKeyboard: + pszHID = Info::tr("USB and PS/2 Keyboard"); + pszMrHID = "combokbd"; + break; + default: + break; + } + SHOW_UTF8_STRING("hidkeyboard", Info::tr("Keyboard Device:"), details == VMINFO_MACHINEREADABLE ? pszMrHID : pszHID); + + ComPtr<ISystemProperties> sysProps; + pVirtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam()); + + /* get the maximum amount of UARTs */ + ULONG maxUARTs = 0; + sysProps->COMGETTER(SerialPortCount)(&maxUARTs); + for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++) + { + ComPtr<ISerialPort> uart; + hrc = machine->GetSerialPort(currentUART, uart.asOutParam()); + if (SUCCEEDED(hrc) && uart) + { + FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "uart%u" : Info::tr("UART %u:"), currentUART + 1); + + /* show the config of this UART */ + BOOL fEnabled; + uart->COMGETTER(Enabled)(&fEnabled); + if (!fEnabled) + { + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("%s=\"off\"\n", szNm); + else + RTPrintf(Info::tr("%-28s disabled\n"), szNm); + } + else + { + ULONG ulIRQ, ulIOBase; + PortMode_T HostMode; + Bstr path; + BOOL fServer; + UartType_T UartType; + uart->COMGETTER(IRQ)(&ulIRQ); + uart->COMGETTER(IOBase)(&ulIOBase); + uart->COMGETTER(Path)(path.asOutParam()); + uart->COMGETTER(Server)(&fServer); + uart->COMGETTER(HostMode)(&HostMode); + uart->COMGETTER(UartType)(&UartType); + + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ); + else + RTPrintf(Info::tr("%-28s I/O base: %#06x, IRQ: %d"), szNm, ulIOBase, ulIRQ); + switch (HostMode) + { + default: + case PortMode_Disconnected: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1); + else + RTPrintf(Info::tr(", disconnected")); + break; + case PortMode_RawFile: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uartmode%d=\"file,%ls\"\n", currentUART + 1, + path.raw()); + else + RTPrintf(Info::tr(", attached to raw file '%ls'\n"), + path.raw()); + break; + case PortMode_TCP: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1, + fServer ? "tcpserver" : "tcpclient", path.raw()); + else + RTPrintf(Info::tr(", attached to tcp (%s) '%ls'"), + fServer ? Info::tr("server") : Info::tr("client"), path.raw()); + break; + case PortMode_HostPipe: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uartmode%d=\"%s,%ls\"\n", currentUART + 1, + fServer ? "server" : "client", path.raw()); + else + RTPrintf(Info::tr(", attached to pipe (%s) '%ls'"), + fServer ? Info::tr("server") : Info::tr("client"), path.raw()); + break; + case PortMode_HostDevice: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uartmode%d=\"%ls\"\n", currentUART + 1, + path.raw()); + else + RTPrintf(Info::tr(", attached to device '%ls'"), path.raw()); + break; + } + switch (UartType) + { + default: + case UartType_U16450: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uarttype%d=\"16450\"\n", currentUART + 1); + else + RTPrintf(", 16450\n"); + break; + case UartType_U16550A: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uarttype%d=\"16550A\"\n", currentUART + 1); + else + RTPrintf(", 16550A\n"); + break; + case UartType_U16750: + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("uarttype%d=\"16750\"\n", currentUART + 1); + else + RTPrintf(", 16750\n"); + break; + } + } + } + } + + /* get the maximum amount of LPTs */ + ULONG maxLPTs = 0; + sysProps->COMGETTER(ParallelPortCount)(&maxLPTs); + for (ULONG currentLPT = 0; currentLPT < maxLPTs; currentLPT++) + { + ComPtr<IParallelPort> lpt; + hrc = machine->GetParallelPort(currentLPT, lpt.asOutParam()); + if (SUCCEEDED(hrc) && lpt) + { + FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "lpt%u" : Info::tr("LPT %u:"), currentLPT + 1); + + /* show the config of this LPT */ + BOOL fEnabled; + lpt->COMGETTER(Enabled)(&fEnabled); + if (!fEnabled) + { + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("%s=\"off\"\n", szNm); + else + RTPrintf(Info::tr("%-28s disabled\n"), szNm); + } + else + { + ULONG ulIRQ, ulIOBase; + Bstr path; + lpt->COMGETTER(IRQ)(&ulIRQ); + lpt->COMGETTER(IOBase)(&ulIOBase); + lpt->COMGETTER(Path)(path.asOutParam()); + + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("%s=\"%#06x,%d\"\n", szNm, ulIOBase, ulIRQ); + else + RTPrintf(Info::tr("%-28s I/O base: %#06x, IRQ: %d"), szNm, ulIOBase, ulIRQ); + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("lptmode%d=\"%ls\"\n", currentLPT + 1, path.raw()); + else + RTPrintf(Info::tr(", attached to device '%ls'\n"), path.raw()); + } + } + } + + ComPtr<IAudioSettings> audioSettings; + ComPtr<IAudioAdapter> audioAdapter; + hrc = machine->COMGETTER(AudioSettings)(audioSettings.asOutParam()); + if (SUCCEEDED(hrc)) + hrc = audioSettings->COMGETTER(Adapter)(audioAdapter.asOutParam()); + if (SUCCEEDED(hrc)) + { + const char *pszDrv = Info::tr("Unknown"); + const char *pszCtrl = Info::tr("Unknown"); + const char *pszCodec = Info::tr("Unknown"); + BOOL fEnabled; + hrc = audioAdapter->COMGETTER(Enabled)(&fEnabled); + if (SUCCEEDED(hrc) && fEnabled) + { + AudioDriverType_T enmDrvType; + hrc = audioAdapter->COMGETTER(AudioDriver)(&enmDrvType); + switch (enmDrvType) + { + case AudioDriverType_Default: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "default"; + else + pszDrv = Info::tr("Default"); + break; + case AudioDriverType_Null: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "null"; + else + pszDrv = Info::tr("Null"); + break; + case AudioDriverType_OSS: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "oss"; + else + pszDrv = "OSS"; + break; + case AudioDriverType_ALSA: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "alsa"; + else + pszDrv = "ALSA"; + break; + case AudioDriverType_Pulse: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "pulse"; + else + pszDrv = "PulseAudio"; + break; + case AudioDriverType_WinMM: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "winmm"; + else + pszDrv = "WINMM"; + break; + case AudioDriverType_DirectSound: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "dsound"; + else + pszDrv = "DirectSound"; + break; + case AudioDriverType_WAS: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "was"; + else + pszDrv = "Windows Audio Session (WAS)"; + break; + case AudioDriverType_CoreAudio: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "coreaudio"; + else + pszDrv = "CoreAudio"; + break; + case AudioDriverType_SolAudio: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "solaudio"; + else + pszDrv = "SolAudio"; + break; + default: + if (details == VMINFO_MACHINEREADABLE) + pszDrv = "unknown"; + break; + } + AudioControllerType_T enmCtrlType; + hrc = audioAdapter->COMGETTER(AudioController)(&enmCtrlType); + switch (enmCtrlType) + { + case AudioControllerType_AC97: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "ac97"; + else + pszCtrl = "AC97"; + break; + case AudioControllerType_SB16: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "sb16"; + else + pszCtrl = "SB16"; + break; + case AudioControllerType_HDA: + if (details == VMINFO_MACHINEREADABLE) + pszCtrl = "hda"; + else + pszCtrl = "HDA"; + break; + default: + break; + } + AudioCodecType_T enmCodecType; + hrc = audioAdapter->COMGETTER(AudioCodec)(&enmCodecType); + switch (enmCodecType) + { + case AudioCodecType_SB16: + pszCodec = "SB16"; + break; + case AudioCodecType_STAC9700: + pszCodec = "STAC9700"; + break; + case AudioCodecType_AD1980: + pszCodec = "AD1980"; + break; + case AudioCodecType_STAC9221: + pszCodec = "STAC9221"; + break; + case AudioCodecType_Null: break; /* Shut up MSC. */ + default: break; + } + } + else + fEnabled = FALSE; + + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("audio=\"%s\"\n", fEnabled ? pszDrv : "none"); + else + { + RTPrintf("%-28s %s", Info::tr("Audio:"), fEnabled ? Info::tr("enabled") : Info::tr("disabled")); + if (fEnabled) + RTPrintf(Info::tr(" (Driver: %s, Controller: %s, Codec: %s)"), pszDrv, pszCtrl, pszCodec); + RTPrintf("\n"); + } + SHOW_BOOLEAN_PROP(audioAdapter, EnabledOut, "audio_out", Info::tr("Audio playback:")); + SHOW_BOOLEAN_PROP(audioAdapter, EnabledIn, "audio_in", Info::tr("Audio capture:")); + + /** @todo Add printing run-time host audio device selection(s) here. */ + } + + /* Shared clipboard */ + { + const char *psz; + ClipboardMode_T enmMode = (ClipboardMode_T)0; + hrc = machine->COMGETTER(ClipboardMode)(&enmMode); + switch (enmMode) + { + case ClipboardMode_Disabled: + psz = "disabled"; + break; + case ClipboardMode_HostToGuest: + psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest"); + break; + case ClipboardMode_GuestToHost: + psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost"); + break; + case ClipboardMode_Bidirectional: + psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional"); + break; + default: + psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown"); + break; + } + SHOW_UTF8_STRING("clipboard", Info::tr("Clipboard Mode:"), psz); +#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS + SHOW_BOOLEAN_PROP(machine, ClipboardFileTransfersEnabled, "clipboard_file_transfers", Info::tr("Clipboard file transfers:")); +#endif + } + + /* Drag and drop */ + { + const char *psz; + DnDMode_T enmMode; + hrc = machine->COMGETTER(DnDMode)(&enmMode); + switch (enmMode) + { + case DnDMode_Disabled: + psz = "disabled"; + break; + case DnDMode_HostToGuest: + psz = details == VMINFO_MACHINEREADABLE ? "hosttoguest" : Info::tr("HostToGuest"); + break; + case DnDMode_GuestToHost: + psz = details == VMINFO_MACHINEREADABLE ? "guesttohost" : Info::tr("GuestToHost"); + break; + case DnDMode_Bidirectional: + psz = details == VMINFO_MACHINEREADABLE ? "bidirectional" : Info::tr("Bidirectional"); + break; + default: + psz = details == VMINFO_MACHINEREADABLE ? "unknown" : Info::tr("Unknown"); + break; + } + SHOW_UTF8_STRING("draganddrop", Info::tr("Drag and drop Mode:"), psz); + } + + { + SessionState_T sessState; + hrc = machine->COMGETTER(SessionState)(&sessState); + if (SUCCEEDED(hrc) && sessState != SessionState_Unlocked) + { + Bstr sessName; + hrc = machine->COMGETTER(SessionName)(sessName.asOutParam()); + if (SUCCEEDED(hrc) && !sessName.isEmpty()) + SHOW_BSTR_STRING("SessionName", Info::tr("Session name:"), sessName); + } + } + + if (pConsole) + { + do + { + ComPtr<IDisplay> display; + hrc = pConsole->COMGETTER(Display)(display.asOutParam()); + if (hrc == E_ACCESSDENIED || display.isNull()) + break; /* VM not powered up */ + if (FAILED(hrc)) + { + com::GlueHandleComError(pConsole, "COMGETTER(Display)(display.asOutParam())", hrc, __FILE__, __LINE__); + return hrc; + } + ULONG xRes, yRes, bpp; + LONG xOrigin, yOrigin; + GuestMonitorStatus_T monitorStatus; + hrc = display->GetScreenResolution(0, &xRes, &yRes, &bpp, &xOrigin, &yOrigin, &monitorStatus); + if (hrc == E_ACCESSDENIED) + break; /* VM not powered up */ + if (FAILED(hrc)) + { + com::ErrorInfo info(display, COM_IIDOF(IDisplay)); + GluePrintErrorInfo(info); + return hrc; + } + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("VideoMode=\"%d,%d,%d\"@%d,%d %d\n", xRes, yRes, bpp, xOrigin, yOrigin, monitorStatus); + else + { + const char *pszMonitorStatus = Info::tr("unknown status"); + switch (monitorStatus) + { + case GuestMonitorStatus_Blank: pszMonitorStatus = Info::tr("blank"); break; + case GuestMonitorStatus_Enabled: pszMonitorStatus = Info::tr("enabled"); break; + case GuestMonitorStatus_Disabled: pszMonitorStatus = Info::tr("disabled"); break; + default: break; + } + RTPrintf("%-28s %dx%dx%d at %d,%d %s\n", Info::tr("Video mode:"), xRes, yRes, bpp, xOrigin, yOrigin, pszMonitorStatus); + } + } + while (0); + } + + /* + * Remote Desktop + */ + ComPtr<IVRDEServer> vrdeServer; + hrc = machine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + if (SUCCEEDED(hrc) && vrdeServer) + { + BOOL fEnabled = false; + vrdeServer->COMGETTER(Enabled)(&fEnabled); + if (fEnabled) + { + LONG currentPort = -1; + Bstr ports; + vrdeServer->GetVRDEProperty(Bstr("TCP/Ports").raw(), ports.asOutParam()); + Bstr address; + vrdeServer->GetVRDEProperty(Bstr("TCP/Address").raw(), address.asOutParam()); + BOOL fMultiCon; + vrdeServer->COMGETTER(AllowMultiConnection)(&fMultiCon); + BOOL fReuseCon; + vrdeServer->COMGETTER(ReuseSingleConnection)(&fReuseCon); + Bstr videoChannel; + vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), videoChannel.asOutParam()); + BOOL fVideoChannel = (videoChannel.compare(Bstr("true"), Bstr::CaseInsensitive)== 0) + || (videoChannel == "1"); + Bstr videoChannelQuality; + vrdeServer->GetVRDEProperty(Bstr("VideoChannel/Quality").raw(), videoChannelQuality.asOutParam()); + AuthType_T authType = (AuthType_T)0; + const char *strAuthType; + vrdeServer->COMGETTER(AuthType)(&authType); + switch (authType) + { + case AuthType_Null: + if (details == VMINFO_MACHINEREADABLE) + strAuthType = "null"; + else + strAuthType = Info::tr("null"); + break; + case AuthType_External: + if (details == VMINFO_MACHINEREADABLE) + strAuthType = "external"; + else + strAuthType = Info::tr("external"); + break; + case AuthType_Guest: + if (details == VMINFO_MACHINEREADABLE) + strAuthType = "guest"; + else + strAuthType = Info::tr("guest"); + break; + default: + if (details == VMINFO_MACHINEREADABLE) + strAuthType = "unknown"; + else + strAuthType = Info::tr("unknown"); + break; + } + if (pConsole) + { + ComPtr<IVRDEServerInfo> vrdeServerInfo; + CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), hrc); + if (!vrdeServerInfo.isNull()) + { + hrc = vrdeServerInfo->COMGETTER(Port)(¤tPort); + if (hrc == E_ACCESSDENIED) + { + currentPort = -1; /* VM not powered up */ + } + else if (FAILED(hrc)) + { + com::ErrorInfo info(vrdeServerInfo, COM_IIDOF(IVRDEServerInfo)); + GluePrintErrorInfo(info); + return hrc; + } + } + } + if (details == VMINFO_MACHINEREADABLE) + { + RTPrintf("vrde=\"on\"\n"); + RTPrintf("vrdeport=%d\n", currentPort); + RTPrintf("vrdeports=\"%ls\"\n", ports.raw()); + RTPrintf("vrdeaddress=\"%ls\"\n", address.raw()); + RTPrintf("vrdeauthtype=\"%s\"\n", strAuthType); + RTPrintf("vrdemulticon=\"%s\"\n", fMultiCon ? "on" : "off"); + RTPrintf("vrdereusecon=\"%s\"\n", fReuseCon ? "on" : "off"); + RTPrintf("vrdevideochannel=\"%s\"\n", fVideoChannel ? "on" : "off"); + if (fVideoChannel) + RTPrintf("vrdevideochannelquality=\"%ls\"\n", videoChannelQuality.raw()); + } + else + { + if (address.isEmpty()) + address = "0.0.0.0"; + RTPrintf(Info::tr("%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s)\n"), + "VRDE:", address.raw(), ports.raw(), fMultiCon ? Info::tr("on") : Info::tr("off"), + fReuseCon ? Info::tr("on") : Info::tr("off"), strAuthType); + if (pConsole && currentPort != -1 && currentPort != 0) + RTPrintf("%-28s %d\n", Info::tr("VRDE port:"), currentPort); + if (fVideoChannel) + RTPrintf(Info::tr("%-28s enabled (Quality %ls)\n"), Info::tr("Video redirection:"), videoChannelQuality.raw()); + else + RTPrintf(Info::tr("%-28s disabled\n"), Info::tr("Video redirection:")); + } + com::SafeArray<BSTR> aProperties; + if (SUCCEEDED(vrdeServer->COMGETTER(VRDEProperties)(ComSafeArrayAsOutParam(aProperties)))) + { + unsigned i; + for (i = 0; i < aProperties.size(); ++i) + { + Bstr value; + vrdeServer->GetVRDEProperty(aProperties[i], value.asOutParam()); + if (details == VMINFO_MACHINEREADABLE) + { + if (value.isEmpty()) + RTPrintf("vrdeproperty[%ls]=<not set>\n", aProperties[i]); + else + RTPrintf("vrdeproperty[%ls]=\"%ls\"\n", aProperties[i], value.raw()); + } + else + { + if (value.isEmpty()) + RTPrintf(Info::tr("%-28s: %-10lS = <not set>\n"), Info::tr("VRDE property"), aProperties[i]); + else + RTPrintf("%-28s: %-10lS = \"%ls\"\n", Info::tr("VRDE property"), aProperties[i], value.raw()); + } + } + } + } + else + { + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("vrde=\"off\"\n"); + else + RTPrintf(Info::tr("%-28s disabled\n"), "VRDE:"); + } + } + + /* + * USB. + */ + SafeIfaceArray<IUSBController> USBCtlColl; + hrc = machine->COMGETTER(USBControllers)(ComSafeArrayAsOutParam(USBCtlColl)); + if (SUCCEEDED(hrc)) + { + bool fOhciEnabled = false; + bool fEhciEnabled = false; + bool fXhciEnabled = false; + + for (unsigned i = 0; i < USBCtlColl.size(); i++) + { + USBControllerType_T enmType; + + hrc = USBCtlColl[i]->COMGETTER(Type)(&enmType); + if (SUCCEEDED(hrc)) + { + switch (enmType) + { + case USBControllerType_OHCI: + fOhciEnabled = true; + break; + case USBControllerType_EHCI: + fEhciEnabled = true; + break; + case USBControllerType_XHCI: + fXhciEnabled = true; + break; + default: + break; + } + } + } + + SHOW_BOOL_VALUE("usb", "OHCI USB:", fOhciEnabled); + SHOW_BOOL_VALUE("ehci", "EHCI USB:", fEhciEnabled); + SHOW_BOOL_VALUE("xhci", "xHCI USB:", fXhciEnabled); + } + + ComPtr<IUSBDeviceFilters> USBFlts; + hrc = machine->COMGETTER(USBDeviceFilters)(USBFlts.asOutParam()); + if (SUCCEEDED(hrc)) + { + SafeIfaceArray <IUSBDeviceFilter> Coll; + hrc = USBFlts->COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(Coll)); + if (SUCCEEDED(hrc)) + { + if (Coll.size() > 0) + { + if (details != VMINFO_MACHINEREADABLE) + RTPrintf(Info::tr("USB Device Filters:\n")); + for (size_t index = 0; index < Coll.size(); ++index) + { + ComPtr<IUSBDeviceFilter> DevPtr = Coll[index]; + + if (details != VMINFO_MACHINEREADABLE) + SHOW_UTF8_STRING("index", Info::tr("Index:"), FmtNm(szNm, "%zu", index)); + SHOW_BOOLEAN_PROP_EX(DevPtr, Active, FmtNm(szNm, "USBFilterActive%zu", index + 1), Info::tr(" Active:"), Info::tr("yes"), Info::tr("no")); + SHOW_STRING_PROP(DevPtr, Name, FmtNm(szNm, "USBFilterName%zu", index + 1), Info::tr(" Name:")); + SHOW_STRING_PROP(DevPtr, VendorId, FmtNm(szNm, "USBFilterVendorId%zu", index + 1), Info::tr(" VendorId:")); + SHOW_STRING_PROP(DevPtr, ProductId, FmtNm(szNm, "USBFilterProductId%zu", index + 1), Info::tr(" ProductId:")); + SHOW_STRING_PROP(DevPtr, Revision, FmtNm(szNm, "USBFilterRevision%zu", index + 1), Info::tr(" Revision:")); + SHOW_STRING_PROP(DevPtr, Manufacturer, FmtNm(szNm, "USBFilterManufacturer%zu", index + 1), Info::tr(" Manufacturer:")); + SHOW_STRING_PROP(DevPtr, Product, FmtNm(szNm, "USBFilterProduct%zu", index + 1), Info::tr(" Product:")); + SHOW_STRING_PROP(DevPtr, Remote, FmtNm(szNm, "USBFilterRemote%zu", index + 1), Info::tr(" Remote:")); + SHOW_STRING_PROP(DevPtr, SerialNumber, FmtNm(szNm, "USBFilterSerialNumber%zu", index + 1), Info::tr(" Serial Number:")); + if (details != VMINFO_MACHINEREADABLE) + { + ULONG fMaskedIfs; + CHECK_ERROR_RET(DevPtr, COMGETTER(MaskedInterfaces)(&fMaskedIfs), hrc); + if (fMaskedIfs) + RTPrintf("%-28s %#010x\n", Info::tr("Masked Interfaces:"), fMaskedIfs); + } + } + } + else if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s %s\n", Info::tr("USB Device Filters:"), Info::tr("<none>")); + } + + if (pConsole) + { + { + SafeIfaceArray<IHostUSBDevice> coll; + CHECK_ERROR_RET(pConsole, COMGETTER(RemoteUSBDevices)(ComSafeArrayAsOutParam(coll)), hrc); + hrc = showUsbDevices(coll, "USBRemote", Info::tr("Available remote USB devices:"), details); + if (FAILED(hrc)) + return hrc; + } + + { + SafeIfaceArray<IUSBDevice> coll; + CHECK_ERROR_RET(pConsole, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)), hrc); + showUsbDevices(coll, "USBAttach", Info::tr("Currently attached USB devices:"), details); + if (FAILED(hrc)) + return hrc; + } + } + } /* USB */ + +#ifdef VBOX_WITH_PCI_PASSTHROUGH + /* Host PCI passthrough devices */ + { + SafeIfaceArray <IPCIDeviceAttachment> assignments; + hrc = machine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments)); + if (SUCCEEDED(hrc)) + { + if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE)) + { + RTPrintf(Info::tr("\nAttached physical PCI devices:\n\n")); + } + + for (size_t index = 0; index < assignments.size(); ++index) + { + ComPtr<IPCIDeviceAttachment> Assignment = assignments[index]; + char szHostPCIAddress[32], szGuestPCIAddress[32]; + LONG iHostPCIAddress = -1, iGuestPCIAddress = -1; + Bstr DevName; + + Assignment->COMGETTER(Name)(DevName.asOutParam()); + Assignment->COMGETTER(HostAddress)(&iHostPCIAddress); + Assignment->COMGETTER(GuestAddress)(&iGuestPCIAddress); + PCIBusAddress().fromLong(iHostPCIAddress).format(szHostPCIAddress, sizeof(szHostPCIAddress)); + PCIBusAddress().fromLong(iGuestPCIAddress).format(szGuestPCIAddress, sizeof(szGuestPCIAddress)); + + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("AttachedHostPCI=%s,%s\n", szHostPCIAddress, szGuestPCIAddress); + else + RTPrintf(Info::tr(" Host device %ls at %s attached as %s\n"), DevName.raw(), szHostPCIAddress, szGuestPCIAddress); + } + + if (assignments.size() > 0 && (details != VMINFO_MACHINEREADABLE)) + { + RTPrintf("\n"); + } + } + } + /* Host PCI passthrough devices */ +#endif + + /* + * Bandwidth groups + */ + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s ", Info::tr("Bandwidth groups:")); + { + ComPtr<IBandwidthControl> bwCtrl; + CHECK_ERROR_RET(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam()), hrc); + + hrc = showBandwidthGroups(bwCtrl, details); + } + + + /* + * Shared folders + */ + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s ", Info::tr("Shared folders:")); + uint32_t numSharedFolders = 0; +#if 0 // not yet implemented + /* globally shared folders first */ + { + SafeIfaceArray <ISharedFolder> sfColl; + CHECK_ERROR_RET(pVirtualBox, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(sfColl)), rc); + for (size_t i = 0; i < sfColl.size(); ++i) + { + ComPtr<ISharedFolder> sf = sfColl[i]; + showSharedFolder(sf, details, Info::tr("global mapping"), "GlobalMapping", i + 1, numSharedFolders == 0); + ++numSharedFolders; + } + } +#endif + /* now VM mappings */ + { + com::SafeIfaceArray <ISharedFolder> folders; + CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc); + for (size_t i = 0; i < folders.size(); ++i) + { + ComPtr<ISharedFolder> sf = folders[i]; + showSharedFolder(sf, details, Info::tr("machine mapping"), "MachineMapping", i + 1, numSharedFolders == 0); + ++numSharedFolders; + } + } + /* transient mappings */ + if (pConsole) + { + com::SafeIfaceArray <ISharedFolder> folders; + CHECK_ERROR_RET(pConsole, COMGETTER(SharedFolders)(ComSafeArrayAsOutParam(folders)), hrc); + for (size_t i = 0; i < folders.size(); ++i) + { + ComPtr<ISharedFolder> sf = folders[i]; + showSharedFolder(sf, details, Info::tr("transient mapping"), "TransientMapping", i + 1, numSharedFolders == 0); + ++numSharedFolders; + } + } + if (details != VMINFO_MACHINEREADABLE) + { + if (!numSharedFolders) + RTPrintf(Info::tr("<none>\n")); + else + RTPrintf("\n"); + } + + if (pConsole) + { + /* + * Live VRDE info. + */ + ComPtr<IVRDEServerInfo> vrdeServerInfo; + CHECK_ERROR_RET(pConsole, COMGETTER(VRDEServerInfo)(vrdeServerInfo.asOutParam()), hrc); + BOOL fActive = FALSE; + ULONG cNumberOfClients = 0; + LONG64 BeginTime = 0; + LONG64 EndTime = 0; + LONG64 BytesSent = 0; + LONG64 BytesSentTotal = 0; + LONG64 BytesReceived = 0; + LONG64 BytesReceivedTotal = 0; + Bstr User; + Bstr Domain; + Bstr ClientName; + Bstr ClientIP; + ULONG ClientVersion = 0; + ULONG EncryptionStyle = 0; + + if (!vrdeServerInfo.isNull()) + { + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Active)(&fActive), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(NumberOfClients)(&cNumberOfClients), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BeginTime)(&BeginTime), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EndTime)(&EndTime), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSent)(&BytesSent), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesSentTotal)(&BytesSentTotal), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceived)(&BytesReceived), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(BytesReceivedTotal)(&BytesReceivedTotal), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(User)(User.asOutParam()), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(Domain)(Domain.asOutParam()), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientName)(ClientName.asOutParam()), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientIP)(ClientIP.asOutParam()), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(ClientVersion)(&ClientVersion), hrc); + CHECK_ERROR_RET(vrdeServerInfo, COMGETTER(EncryptionStyle)(&EncryptionStyle), hrc); + } + + SHOW_BOOL_VALUE_EX("VRDEActiveConnection", Info::tr("VRDE Connection:"), fActive, Info::tr("active"), Info::tr("not active")); + SHOW_ULONG_VALUE("VRDEClients=", Info::tr("Clients so far:"), cNumberOfClients, ""); + + if (cNumberOfClients > 0) + { + char szTimeValue[128]; + makeTimeStr(szTimeValue, sizeof(szTimeValue), BeginTime); + if (fActive) + SHOW_UTF8_STRING("VRDEStartTime", Info::tr("Start time:"), szTimeValue); + else + { + SHOW_UTF8_STRING("VRDELastStartTime", Info::tr("Last started:"), szTimeValue); + makeTimeStr(szTimeValue, sizeof(szTimeValue), EndTime); + SHOW_UTF8_STRING("VRDELastEndTime", Info::tr("Last ended:"), szTimeValue); + } + + int64_t ThroughputSend = 0; + int64_t ThroughputReceive = 0; + if (EndTime != BeginTime) + { + ThroughputSend = (BytesSent * 1000) / (EndTime - BeginTime); + ThroughputReceive = (BytesReceived * 1000) / (EndTime - BeginTime); + } + SHOW_LONG64_VALUE("VRDEBytesSent", Info::tr("Sent:"), BytesSent, Info::tr("Bytes")); + SHOW_LONG64_VALUE("VRDEThroughputSend", Info::tr("Average speed:"), ThroughputSend, Info::tr("B/s")); + SHOW_LONG64_VALUE("VRDEBytesSentTotal", Info::tr("Sent total:"), BytesSentTotal, Info::tr("Bytes")); + + SHOW_LONG64_VALUE("VRDEBytesReceived", Info::tr("Received:"), BytesReceived, Info::tr("Bytes")); + SHOW_LONG64_VALUE("VRDEThroughputReceive", Info::tr("Speed:"), ThroughputReceive, Info::tr("B/s")); + SHOW_LONG64_VALUE("VRDEBytesReceivedTotal", Info::tr("Received total:"), BytesReceivedTotal, Info::tr("Bytes")); + + if (fActive) + { + SHOW_BSTR_STRING("VRDEUserName", Info::tr("User name:"), User); + SHOW_BSTR_STRING("VRDEDomain", Info::tr("Domain:"), Domain); + SHOW_BSTR_STRING("VRDEClientName", Info::tr("Client name:"), ClientName); + SHOW_BSTR_STRING("VRDEClientIP", Info::tr("Client IP:"), ClientIP); + SHOW_ULONG_VALUE("VRDEClientVersion", Info::tr("Client version:"), ClientVersion, ""); + SHOW_UTF8_STRING("VRDEEncryption", Info::tr("Encryption:"), EncryptionStyle == 0 ? "RDP4" : "RDP5 (X.509)"); + } + } + } + +#ifdef VBOX_WITH_RECORDING + { + ComPtr<IRecordingSettings> recordingSettings; + CHECK_ERROR_RET(machine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam()), hrc); + + BOOL fEnabled; + CHECK_ERROR_RET(recordingSettings, COMGETTER(Enabled)(&fEnabled), hrc); + SHOW_BOOL_VALUE_EX("recording_enabled", Info::tr("Recording enabled:"), fEnabled, Info::tr("yes"), Info::tr("no")); + + SafeIfaceArray <IRecordingScreenSettings> saScreenSettings; + CHECK_ERROR_RET(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saScreenSettings)), hrc); + + SHOW_ULONG_VALUE("recording_screens", Info::tr("Recording screens:"), saScreenSettings.size(), ""); + + for (size_t i = 0; i < saScreenSettings.size(); ++i) + { + ComPtr<IRecordingScreenSettings> screenSettings = saScreenSettings[i]; + + FmtNm(szNm, details == VMINFO_MACHINEREADABLE ? "rec_screen%zu" : Info::tr("Screen %u:"), i); + RTPrintf(Info::tr(" %s\n"), szNm); + + CHECK_ERROR_RET(screenSettings, COMGETTER(Enabled)(&fEnabled), hrc); + ULONG idScreen; + CHECK_ERROR_RET(screenSettings, COMGETTER(Id)(&idScreen), hrc); + com::SafeArray<RecordingFeature_T> vecFeatures; + CHECK_ERROR_RET(screenSettings, COMGETTER(Features)(ComSafeArrayAsOutParam(vecFeatures)), hrc); + ULONG Width; + CHECK_ERROR_RET(screenSettings, COMGETTER(VideoWidth)(&Width), hrc); + ULONG Height; + CHECK_ERROR_RET(screenSettings, COMGETTER(VideoHeight)(&Height), hrc); + ULONG Rate; + CHECK_ERROR_RET(screenSettings, COMGETTER(VideoRate)(&Rate), hrc); + ULONG Fps; + CHECK_ERROR_RET(screenSettings, COMGETTER(VideoFPS)(&Fps), hrc); + RecordingDestination_T enmDst; + CHECK_ERROR_RET(screenSettings, COMGETTER(Destination)(&enmDst), hrc); + Bstr bstrFile; + CHECK_ERROR_RET(screenSettings, COMGETTER(Filename)(bstrFile.asOutParam()), hrc); + Bstr bstrOptions; + CHECK_ERROR_RET(screenSettings, COMGETTER(Options)(bstrOptions.asOutParam()), hrc); + + BOOL fRecordVideo = FALSE; +# ifdef VBOX_WITH_AUDIO_RECORDING + BOOL fRecordAudio = FALSE; +# endif + for (size_t f = 0; f < vecFeatures.size(); ++f) + { + if (vecFeatures[f] == RecordingFeature_Video) + fRecordVideo = TRUE; +# ifdef VBOX_WITH_AUDIO_RECORDING + else if (vecFeatures[f] == RecordingFeature_Audio) + fRecordAudio = TRUE; +# endif + } + + SHOW_BOOL_VALUE_EX("rec_screen_enabled", Info::tr(" Enabled:"), fEnabled, + Info::tr("yes"), Info::tr("no")); + SHOW_ULONG_VALUE ("rec_screen_id", Info::tr(" ID:"), idScreen, ""); + SHOW_BOOL_VALUE_EX("rec_screen_video_enabled", Info::tr(" Record video:"), fRecordVideo, + Info::tr("yes"), Info::tr("no")); +# ifdef VBOX_WITH_AUDIO_RECORDING + SHOW_BOOL_VALUE_EX("rec_screen_audio_enabled", Info::tr(" Record audio:"), fRecordAudio, + Info::tr("yes"), Info::tr("no")); +# endif + SHOW_UTF8_STRING("rec_screen_dest", Info::tr(" Destination:"), + enmDst == RecordingDestination_File + ? Info::tr("File") : Info::tr("Unknown")); + /** @todo Implement other destinations. */ + if (enmDst == RecordingDestination_File) + SHOW_BSTR_STRING("rec_screen_dest_filename", Info::tr(" File:"), bstrFile); + + SHOW_BSTR_STRING ("rec_screen_opts", Info::tr(" Options:"), bstrOptions); + + /* Video properties. */ + RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height); + SHOW_UTF8_STRING ("rec_screen_video_res_xy", Info::tr(" Video dimensions:"), szValue); + SHOW_ULONG_VALUE ("rec_screen_video_rate_kbps", Info::tr(" Video rate:"), Rate, Info::tr("kbps")); + SHOW_ULONG_VALUE ("rec_screen_video_fps", Info::tr(" Video FPS:"), Fps, Info::tr("fps")); + + /** @todo Add more audio capturing profile / information here. */ + } + } +#endif /* VBOX_WITH_RECORDING */ + + if ( details == VMINFO_STANDARD + || details == VMINFO_FULL + || details == VMINFO_MACHINEREADABLE) + { + Bstr description; + machine->COMGETTER(Description)(description.asOutParam()); + if (!description.isEmpty()) + { + if (details == VMINFO_MACHINEREADABLE) + outputMachineReadableString("description", &description); + else + RTPrintf(Info::tr("Description:\n%ls\n"), description.raw()); + } + } + + /* VMMDev testing config (extra data) */ + if (details != VMINFO_MACHINEREADABLE) + { + Bstr bstr; + CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled").raw(), + bstr.asOutParam()), hrcCheck); + int const fEnabled = parseCfgmBool(&bstr); + + CHECK_ERROR2I_RET(machine, GetExtraData(Bstr("VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO").raw(), + bstr.asOutParam()), hrcCheck); + int const fMmio = parseCfgmBool(&bstr); + if (fEnabled || fMmio) + { + RTPrintf("%-28s %s, %s %s\n", + Info::tr("VMMDev Testing"), + fEnabled > 0 ? Info::tr("enabled") : fEnabled == 0 ? Info::tr("disabled") : Info::tr("misconfigured"), + "MMIO:", + fMmio > 0 ? Info::tr("enabled") : fMmio == 0 ? Info::tr("disabled") : Info::tr("misconfigured")); + for (uint32_t i = 0; i < 10; i++) + { + BstrFmt bstrName("VBoxInternal/Devices/VMMDev/0/Config/TestingCfgDword%u", i); + CHECK_ERROR2I_RET(machine, GetExtraData(bstrName.raw(), bstr.asOutParam()), hrcCheck); + if (bstr.isNotEmpty()) + RTPrintf("%-28s %ls\n", FmtNm(szNm, "VMMDev Testing Cfg Dword%u:", i), bstr.raw()); + } + } + } + + /* + * Snapshots. + */ + ComPtr<ISnapshot> snapshot; + hrc = machine->FindSnapshot(Bstr().raw(), snapshot.asOutParam()); + if (SUCCEEDED(hrc) && snapshot) + { + ComPtr<ISnapshot> currentSnapshot; + hrc = machine->COMGETTER(CurrentSnapshot)(currentSnapshot.asOutParam()); + if (SUCCEEDED(hrc)) + { + if (details != VMINFO_MACHINEREADABLE) + RTPrintf(Info::tr("* Snapshots:\n")); + showSnapshots(snapshot, currentSnapshot, details); + } + } + + /* + * Guest stuff (mainly interesting when running). + */ + if (details != VMINFO_MACHINEREADABLE) + RTPrintf(Info::tr("* Guest:\n")); + + SHOW_ULONG_PROP(machine, MemoryBalloonSize, "GuestMemoryBalloon", + Info::tr("Configured memory balloon:"), Info::tr("MB")); + + if (pConsole) + { + ComPtr<IGuest> guest; + hrc = pConsole->COMGETTER(Guest)(guest.asOutParam()); + if (SUCCEEDED(hrc) && !guest.isNull()) + { + SHOW_STRING_PROP_NOT_EMPTY(guest, OSTypeId, "GuestOSType", Info::tr("OS type:")); + + AdditionsRunLevelType_T guestRunLevel; /** @todo Add a runlevel-to-string (e.g. 0 = "None") method? */ + hrc = guest->COMGETTER(AdditionsRunLevel)(&guestRunLevel); + if (SUCCEEDED(hrc)) + SHOW_ULONG_VALUE("GuestAdditionsRunLevel", Info::tr("Additions run level:"), (ULONG)guestRunLevel, ""); + + Bstr guestString; + hrc = guest->COMGETTER(AdditionsVersion)(guestString.asOutParam()); + if ( SUCCEEDED(hrc) + && !guestString.isEmpty()) + { + ULONG uRevision; + hrc = guest->COMGETTER(AdditionsRevision)(&uRevision); + if (FAILED(hrc)) + uRevision = 0; + RTStrPrintf(szValue, sizeof(szValue), "%ls r%u", guestString.raw(), uRevision); + SHOW_UTF8_STRING("GuestAdditionsVersion", Info::tr("Additions version:"), szValue); + } + + /* Print information about known Guest Additions facilities: */ + SafeIfaceArray <IAdditionsFacility> collFac; + CHECK_ERROR_RET(guest, COMGETTER(Facilities)(ComSafeArrayAsOutParam(collFac)), hrc); + if (collFac.size() > 0) + { + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%s\n", Info::tr("Guest Facilities:")); + LONG64 lLastUpdatedMS; + char szLastUpdated[32]; + AdditionsFacilityStatus_T curStatus; + for (size_t index = 0; index < collFac.size(); ++index) + { + ComPtr<IAdditionsFacility> fac = collFac[index]; + if (fac) + { + CHECK_ERROR_RET(fac, COMGETTER(Name)(guestString.asOutParam()), hrc); + if (!guestString.isEmpty()) + { + CHECK_ERROR_RET(fac, COMGETTER(Status)(&curStatus), hrc); + CHECK_ERROR_RET(fac, COMGETTER(LastUpdated)(&lLastUpdatedMS), hrc); + if (details == VMINFO_MACHINEREADABLE) + RTPrintf("GuestAdditionsFacility_%ls=%u,%lld\n", + guestString.raw(), curStatus, lLastUpdatedMS); + else + { + makeTimeStr(szLastUpdated, sizeof(szLastUpdated), lLastUpdatedMS); + RTPrintf(Info::tr("Facility \"%ls\": %s (last update: %s)\n"), + guestString.raw(), facilityStateToName(curStatus, false /* No short naming */), szLastUpdated); + } + } + else + AssertMsgFailed(("Facility with undefined name retrieved!\n")); + } + else + AssertMsgFailed(("Invalid facility returned!\n")); + } + } + else if (details != VMINFO_MACHINEREADABLE) + RTPrintf("%-28s %s\n", Info::tr("Guest Facilities:"), Info::tr("<none>")); + } + } + + if (details != VMINFO_MACHINEREADABLE) + RTPrintf("\n"); + return S_OK; +} + +#if defined(_MSC_VER) +# pragma optimize("", on) +# pragma warning(pop) +#endif + +static const RTGETOPTDEF g_aShowVMInfoOptions[] = +{ + { "--details", 'D', RTGETOPT_REQ_NOTHING }, + { "-details", 'D', RTGETOPT_REQ_NOTHING }, // deprecated + { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING }, + { "-machinereadable", 'M', RTGETOPT_REQ_NOTHING }, // deprecated + { "--log", 'l', RTGETOPT_REQ_UINT32 }, + { "--password-id", 'i', RTGETOPT_REQ_STRING }, + { "-password-id", 'i', RTGETOPT_REQ_STRING }, + { "--password", 'w', RTGETOPT_REQ_STRING }, + { "-password", 'w', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleShowVMInfo(HandlerArg *a) +{ + HRESULT hrc; + const char *VMNameOrUuid = NULL; + bool fLog = false; + uint32_t uLogIdx = 0; + bool fDetails = false; + bool fMachinereadable = false; + Bstr bstrPasswordId; + const char *pszPassword = NULL; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aShowVMInfoOptions, RT_ELEMENTS(g_aShowVMInfoOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'D': // --details + fDetails = true; + break; + + case 'M': // --machinereadable + fMachinereadable = true; + break; + + case 'l': // --log + fLog = true; + uLogIdx = ValueUnion.u32; + break; + + case 'i': // --password-id + bstrPasswordId = ValueUnion.psz; + break; + + case 'w': // --password + pszPassword = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!VMNameOrUuid) + VMNameOrUuid = ValueUnion.psz; + else + return errorSyntax(Info::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* check for required options */ + if (!VMNameOrUuid) + return errorSyntax(Info::tr("VM name or UUID required")); + + /* try to find the given machine */ + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMNameOrUuid).raw(), + machine.asOutParam())); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + /* Printing the log is exclusive. */ + if (fLog && (fMachinereadable || fDetails)) + return errorSyntax(Info::tr("Option --log is exclusive")); + + /* add VM password if required */ + if (pszPassword && bstrPasswordId.isNotEmpty()) + { + Utf8Str strPassword; + if (!RTStrCmp(pszPassword, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPassword, &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read new password from file"); + return rcExit; + } + } + CHECK_ERROR(machine, AddEncryptionPassword(bstrPasswordId.raw(), Bstr(strPassword).raw())); + } + + if (fLog) + { + ULONG64 uOffset = 0; + SafeArray<BYTE> aLogData; + size_t cbLogData; + while (true) + { + /* Reset the array */ + aLogData.setNull(); + /* Fetch a chunk of the log file */ + CHECK_ERROR_BREAK(machine, ReadLog(uLogIdx, uOffset, _1M, + ComSafeArrayAsOutParam(aLogData))); + cbLogData = aLogData.size(); + if (cbLogData == 0) + break; + /* aLogData has a platform dependent line ending, standardize on + * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on + * Windows. Otherwise we end up with CR/CR/LF on Windows. */ + size_t cbLogDataPrint = cbLogData; + for (BYTE *s = aLogData.raw(), *d = s; + s - aLogData.raw() < (ssize_t)cbLogData; + s++, d++) + { + if (*s == '\r') + { + /* skip over CR, adjust destination */ + d--; + cbLogDataPrint--; + } + else if (s != d) + *d = *s; + } + RTStrmWrite(g_pStdOut, aLogData.raw(), cbLogDataPrint); + uOffset += cbLogData; + } + } + else + { + /* 2nd option can be -details or -argdump */ + VMINFO_DETAILS details = VMINFO_NONE; + if (fMachinereadable) + details = VMINFO_MACHINEREADABLE; + else if (fDetails) + details = VMINFO_FULL; + else + details = VMINFO_STANDARD; + + /* open an existing session for the VM */ + hrc = machine->LockMachine(a->session, LockType_Shared); + if (SUCCEEDED(hrc)) + /* get the session machine */ + hrc = a->session->COMGETTER(Machine)(machine.asOutParam()); + + hrc = showVMInfo(a->virtualBox, machine, a->session, details); + + a->session->UnlockMachine(); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp new file mode 100644 index 00000000..f2ed947d --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageList.cpp @@ -0,0 +1,2434 @@ +/* $Id: VBoxManageList.cpp $ */ +/** @file + * VBoxManage - The 'list' command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> + +#include <VBox/com/VirtualBox.h> + +#include <VBox/log.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/time.h> +#include <iprt/getopt.h> +#include <iprt/ctype.h> + +#include <vector> +#include <algorithm> + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(List); + +#ifdef VBOX_WITH_HOSTNETIF_API +static const char *getHostIfMediumTypeText(HostNetworkInterfaceMediumType_T enmType) +{ + switch (enmType) + { + case HostNetworkInterfaceMediumType_Ethernet: return "Ethernet"; + case HostNetworkInterfaceMediumType_PPP: return "PPP"; + case HostNetworkInterfaceMediumType_SLIP: return "SLIP"; + case HostNetworkInterfaceMediumType_Unknown: return List::tr("Unknown"); +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case HostNetworkInterfaceMediumType_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + return List::tr("unknown"); +} + +static const char *getHostIfStatusText(HostNetworkInterfaceStatus_T enmStatus) +{ + switch (enmStatus) + { + case HostNetworkInterfaceStatus_Up: return List::tr("Up"); + case HostNetworkInterfaceStatus_Down: return List::tr("Down"); + case HostNetworkInterfaceStatus_Unknown: return List::tr("Unknown"); +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case HostNetworkInterfaceStatus_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + return List::tr("unknown"); +} +#endif /* VBOX_WITH_HOSTNETIF_API */ + +static const char*getDeviceTypeText(DeviceType_T enmType) +{ + switch (enmType) + { + case DeviceType_HardDisk: return List::tr("HardDisk"); + case DeviceType_DVD: return "DVD"; + case DeviceType_Floppy: return List::tr("Floppy"); + /* Make MSC happy */ + case DeviceType_Null: return "Null"; + case DeviceType_Network: return List::tr("Network"); + case DeviceType_USB: return "USB"; + case DeviceType_SharedFolder: return List::tr("SharedFolder"); + case DeviceType_Graphics3D: return List::tr("Graphics3D"); + case DeviceType_End: break; /* Shut up compiler warnings. */ +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case DeviceType_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + return List::tr("Unknown"); +} + + +/** + * List internal networks. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listInternalNetworks(const ComPtr<IVirtualBox> pVirtualBox) +{ + HRESULT hrc; + com::SafeArray<BSTR> internalNetworks; + CHECK_ERROR(pVirtualBox, COMGETTER(InternalNetworks)(ComSafeArrayAsOutParam(internalNetworks))); + for (size_t i = 0; i < internalNetworks.size(); ++i) + { + RTPrintf(List::tr("Name: %ls\n"), internalNetworks[i]); + } + return hrc; +} + + +/** + * List network interfaces information (bridged/host only). + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + * @param fIsBridged Selects between listing host interfaces (for + * use with bridging) or host only interfaces. + */ +static HRESULT listNetworkInterfaces(const ComPtr<IVirtualBox> pVirtualBox, + bool fIsBridged) +{ + HRESULT hrc; + ComPtr<IHost> host; + CHECK_ERROR(pVirtualBox, COMGETTER(Host)(host.asOutParam())); + com::SafeIfaceArray<IHostNetworkInterface> hostNetworkInterfaces; +#if defined(VBOX_WITH_NETFLT) + if (fIsBridged) + CHECK_ERROR(host, FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_Bridged, + ComSafeArrayAsOutParam(hostNetworkInterfaces))); + else + CHECK_ERROR(host, FindHostNetworkInterfacesOfType(HostNetworkInterfaceType_HostOnly, + ComSafeArrayAsOutParam(hostNetworkInterfaces))); +#else + RT_NOREF(fIsBridged); + CHECK_ERROR(host, COMGETTER(NetworkInterfaces)(ComSafeArrayAsOutParam(hostNetworkInterfaces))); +#endif + for (size_t i = 0; i < hostNetworkInterfaces.size(); ++i) + { + ComPtr<IHostNetworkInterface> networkInterface = hostNetworkInterfaces[i]; +#ifndef VBOX_WITH_HOSTNETIF_API + Bstr interfaceName; + networkInterface->COMGETTER(Name)(interfaceName.asOutParam()); + RTPrintf(List::tr("Name: %ls\n"), interfaceName.raw()); + Guid interfaceGuid; + networkInterface->COMGETTER(Id)(interfaceGuid.asOutParam()); + RTPrintf("GUID: %ls\n\n", Bstr(interfaceGuid.toString()).raw()); +#else /* VBOX_WITH_HOSTNETIF_API */ + Bstr interfaceName; + networkInterface->COMGETTER(Name)(interfaceName.asOutParam()); + RTPrintf(List::tr("Name: %ls\n"), interfaceName.raw()); + Bstr interfaceGuid; + networkInterface->COMGETTER(Id)(interfaceGuid.asOutParam()); + RTPrintf("GUID: %ls\n", interfaceGuid.raw()); + BOOL fDHCPEnabled = FALSE; + networkInterface->COMGETTER(DHCPEnabled)(&fDHCPEnabled); + RTPrintf("DHCP: %s\n", fDHCPEnabled ? List::tr("Enabled") : List::tr("Disabled")); + + Bstr IPAddress; + networkInterface->COMGETTER(IPAddress)(IPAddress.asOutParam()); + RTPrintf(List::tr("IPAddress: %ls\n"), IPAddress.raw()); + Bstr NetworkMask; + networkInterface->COMGETTER(NetworkMask)(NetworkMask.asOutParam()); + RTPrintf(List::tr("NetworkMask: %ls\n"), NetworkMask.raw()); + Bstr IPV6Address; + networkInterface->COMGETTER(IPV6Address)(IPV6Address.asOutParam()); + RTPrintf(List::tr("IPV6Address: %ls\n"), IPV6Address.raw()); + ULONG IPV6NetworkMaskPrefixLength; + networkInterface->COMGETTER(IPV6NetworkMaskPrefixLength)(&IPV6NetworkMaskPrefixLength); + RTPrintf(List::tr("IPV6NetworkMaskPrefixLength: %d\n"), IPV6NetworkMaskPrefixLength); + Bstr HardwareAddress; + networkInterface->COMGETTER(HardwareAddress)(HardwareAddress.asOutParam()); + RTPrintf(List::tr("HardwareAddress: %ls\n"), HardwareAddress.raw()); + HostNetworkInterfaceMediumType_T Type; + networkInterface->COMGETTER(MediumType)(&Type); + RTPrintf(List::tr("MediumType: %s\n"), getHostIfMediumTypeText(Type)); + BOOL fWireless = FALSE; + networkInterface->COMGETTER(Wireless)(&fWireless); + RTPrintf(List::tr("Wireless: %s\n"), fWireless ? List::tr("Yes") : List::tr("No")); + HostNetworkInterfaceStatus_T Status; + networkInterface->COMGETTER(Status)(&Status); + RTPrintf(List::tr("Status: %s\n"), getHostIfStatusText(Status)); + Bstr netName; + networkInterface->COMGETTER(NetworkName)(netName.asOutParam()); + RTPrintf(List::tr("VBoxNetworkName: %ls\n\n"), netName.raw()); +#endif + } + return hrc; +} + + +#ifdef VBOX_WITH_VMNET +/** + * List configured host-only networks. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + * @param Reserved Placeholder! + */ +static HRESULT listHostOnlyNetworks(const ComPtr<IVirtualBox> pVirtualBox) +{ + HRESULT hrc; + com::SafeIfaceArray<IHostOnlyNetwork> hostOnlyNetworks; + CHECK_ERROR(pVirtualBox, COMGETTER(HostOnlyNetworks)(ComSafeArrayAsOutParam(hostOnlyNetworks))); + for (size_t i = 0; i < hostOnlyNetworks.size(); ++i) + { + ComPtr<IHostOnlyNetwork> hostOnlyNetwork = hostOnlyNetworks[i]; + Bstr bstrNetworkName; + CHECK_ERROR2I(hostOnlyNetwork, COMGETTER(NetworkName)(bstrNetworkName.asOutParam())); + RTPrintf(List::tr("Name: %ls\n"), bstrNetworkName.raw()); + + Bstr bstr; + CHECK_ERROR(hostOnlyNetwork, COMGETTER(Id)(bstr.asOutParam())); + RTPrintf("GUID: %ls\n\n", bstr.raw()); + + BOOL fEnabled = FALSE; + CHECK_ERROR2I(hostOnlyNetwork, COMGETTER(Enabled)(&fEnabled)); + RTPrintf(List::tr("State: %s\n"), fEnabled ? List::tr("Enabled") : List::tr("Disabled")); + + CHECK_ERROR2I(hostOnlyNetwork, COMGETTER(NetworkMask)(bstr.asOutParam())); + RTPrintf(List::tr("NetworkMask: %ls\n"), bstr.raw()); + + CHECK_ERROR2I(hostOnlyNetwork, COMGETTER(LowerIP)(bstr.asOutParam())); + RTPrintf(List::tr("LowerIP: %ls\n"), bstr.raw()); + + CHECK_ERROR2I(hostOnlyNetwork, COMGETTER(UpperIP)(bstr.asOutParam())); + RTPrintf(List::tr("UpperIP: %ls\n"), bstr.raw()); + + // CHECK_ERROR2I(hostOnlyNetwork, COMGETTER(Id)(bstr.asOutParam()); + // RTPrintf("NetworkId: %ls\n", bstr.raw()); + + RTPrintf(List::tr("VBoxNetworkName: hostonly-%ls\n\n"), bstrNetworkName.raw()); + } + return hrc; +} +#endif /* VBOX_WITH_VMNET */ + + +#ifdef VBOX_WITH_CLOUD_NET +/** + * List configured cloud network attachments. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + * @param Reserved Placeholder! + */ +static HRESULT listCloudNetworks(const ComPtr<IVirtualBox> pVirtualBox) +{ + com::SafeIfaceArray<ICloudNetwork> cloudNetworks; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(CloudNetworks)(ComSafeArrayAsOutParam(cloudNetworks)), hrcCheck); + for (size_t i = 0; i < cloudNetworks.size(); ++i) + { + ComPtr<ICloudNetwork> cloudNetwork = cloudNetworks[i]; + Bstr networkName; + cloudNetwork->COMGETTER(NetworkName)(networkName.asOutParam()); + RTPrintf(List::tr("Name: %ls\n"), networkName.raw()); + // Guid interfaceGuid; + // cloudNetwork->COMGETTER(Id)(interfaceGuid.asOutParam()); + // RTPrintf("GUID: %ls\n\n", Bstr(interfaceGuid.toString()).raw()); + BOOL fEnabled = FALSE; + cloudNetwork->COMGETTER(Enabled)(&fEnabled); + RTPrintf(List::tr("State: %s\n"), fEnabled ? List::tr("Enabled") : List::tr("Disabled")); + + Bstr Provider; + cloudNetwork->COMGETTER(Provider)(Provider.asOutParam()); + RTPrintf(List::tr("CloudProvider: %ls\n"), Provider.raw()); + Bstr Profile; + cloudNetwork->COMGETTER(Profile)(Profile.asOutParam()); + RTPrintf(List::tr("CloudProfile: %ls\n"), Profile.raw()); + Bstr NetworkId; + cloudNetwork->COMGETTER(NetworkId)(NetworkId.asOutParam()); + RTPrintf(List::tr("CloudNetworkId: %ls\n"), NetworkId.raw()); + Bstr netName = BstrFmt("cloud-%ls", networkName.raw()); + RTPrintf(List::tr("VBoxNetworkName: %ls\n\n"), netName.raw()); + } + return S_OK; +} +#endif /* VBOX_WITH_CLOUD_NET */ + + +/** + * List host information. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listHostInfo(const ComPtr<IVirtualBox> pVirtualBox) +{ + static struct + { + ProcessorFeature_T feature; + const char *pszName; + } features[] + = + { + { ProcessorFeature_HWVirtEx, List::tr("HW virtualization") }, + { ProcessorFeature_PAE, "PAE" }, + { ProcessorFeature_LongMode, List::tr("long mode") }, + { ProcessorFeature_NestedPaging, List::tr("nested paging") }, + { ProcessorFeature_UnrestrictedGuest, List::tr("unrestricted guest") }, + { ProcessorFeature_NestedHWVirt, List::tr("nested HW virtualization") }, + { ProcessorFeature_VirtVmsaveVmload, List::tr("virt. vmsave/vmload") }, + }; + HRESULT hrc; + ComPtr<IHost> Host; + CHECK_ERROR(pVirtualBox, COMGETTER(Host)(Host.asOutParam())); + + RTPrintf(List::tr("Host Information:\n\n")); + + LONG64 u64UtcTime = 0; + CHECK_ERROR(Host, COMGETTER(UTCTime)(&u64UtcTime)); + RTTIMESPEC timeSpec; + char szTime[32]; + RTPrintf(List::tr("Host time: %s\n"), RTTimeSpecToString(RTTimeSpecSetMilli(&timeSpec, u64UtcTime), szTime, sizeof(szTime))); + + ULONG processorOnlineCount = 0; + CHECK_ERROR(Host, COMGETTER(ProcessorOnlineCount)(&processorOnlineCount)); + RTPrintf(List::tr("Processor online count: %lu\n"), processorOnlineCount); + ULONG processorCount = 0; + CHECK_ERROR(Host, COMGETTER(ProcessorCount)(&processorCount)); + RTPrintf(List::tr("Processor count: %lu\n"), processorCount); + ULONG processorOnlineCoreCount = 0; + CHECK_ERROR(Host, COMGETTER(ProcessorOnlineCoreCount)(&processorOnlineCoreCount)); + RTPrintf(List::tr("Processor online core count: %lu\n"), processorOnlineCoreCount); + ULONG processorCoreCount = 0; + CHECK_ERROR(Host, COMGETTER(ProcessorCoreCount)(&processorCoreCount)); + RTPrintf(List::tr("Processor core count: %lu\n"), processorCoreCount); + for (unsigned i = 0; i < RT_ELEMENTS(features); i++) + { + BOOL supported; + CHECK_ERROR(Host, GetProcessorFeature(features[i].feature, &supported)); + RTPrintf(List::tr("Processor supports %s: %s\n"), features[i].pszName, supported ? List::tr("yes") : List::tr("no")); + } + for (ULONG i = 0; i < processorCount; i++) + { + ULONG processorSpeed = 0; + CHECK_ERROR(Host, GetProcessorSpeed(i, &processorSpeed)); + if (processorSpeed) + RTPrintf(List::tr("Processor#%u speed: %lu MHz\n"), i, processorSpeed); + else + RTPrintf(List::tr("Processor#%u speed: unknown\n"), i); + Bstr processorDescription; + CHECK_ERROR(Host, GetProcessorDescription(i, processorDescription.asOutParam())); + RTPrintf(List::tr("Processor#%u description: %ls\n"), i, processorDescription.raw()); + } + + ULONG memorySize = 0; + CHECK_ERROR(Host, COMGETTER(MemorySize)(&memorySize)); + RTPrintf(List::tr("Memory size: %lu MByte\n", "", memorySize), memorySize); + + ULONG memoryAvailable = 0; + CHECK_ERROR(Host, COMGETTER(MemoryAvailable)(&memoryAvailable)); + RTPrintf(List::tr("Memory available: %lu MByte\n", "", memoryAvailable), memoryAvailable); + + Bstr operatingSystem; + CHECK_ERROR(Host, COMGETTER(OperatingSystem)(operatingSystem.asOutParam())); + RTPrintf(List::tr("Operating system: %ls\n"), operatingSystem.raw()); + + Bstr oSVersion; + CHECK_ERROR(Host, COMGETTER(OSVersion)(oSVersion.asOutParam())); + RTPrintf(List::tr("Operating system version: %ls\n"), oSVersion.raw()); + return hrc; +} + + +/** + * List media information. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + * @param aMedia Medium objects to list information for. + * @param pszParentUUIDStr String with the parent UUID string (or "base"). + * @param fOptLong Long (@c true) or short list format. + */ +static HRESULT listMedia(const ComPtr<IVirtualBox> pVirtualBox, + const com::SafeIfaceArray<IMedium> &aMedia, + const char *pszParentUUIDStr, + bool fOptLong) +{ + HRESULT hrc = S_OK; + for (size_t i = 0; i < aMedia.size(); ++i) + { + ComPtr<IMedium> pMedium = aMedia[i]; + + hrc = showMediumInfo(pVirtualBox, pMedium, pszParentUUIDStr, fOptLong); + + RTPrintf("\n"); + + com::SafeIfaceArray<IMedium> children; + CHECK_ERROR(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(children))); + if (children.size() > 0) + { + Bstr uuid; + pMedium->COMGETTER(Id)(uuid.asOutParam()); + + // depth first listing of child media + hrc = listMedia(pVirtualBox, children, Utf8Str(uuid).c_str(), fOptLong); + } + } + + return hrc; +} + + +/** + * List virtual image backends. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listHddBackends(const ComPtr<IVirtualBox> pVirtualBox) +{ + HRESULT hrc; + ComPtr<ISystemProperties> systemProperties; + CHECK_ERROR(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam())); + com::SafeIfaceArray<IMediumFormat> mediumFormats; + CHECK_ERROR(systemProperties, COMGETTER(MediumFormats)(ComSafeArrayAsOutParam(mediumFormats))); + + RTPrintf(List::tr("Supported hard disk backends:\n\n")); + for (size_t i = 0; i < mediumFormats.size(); ++i) + { + /* General information */ + Bstr id; + CHECK_ERROR(mediumFormats[i], COMGETTER(Id)(id.asOutParam())); + + Bstr description; + CHECK_ERROR(mediumFormats[i], + COMGETTER(Name)(description.asOutParam())); + + ULONG caps = 0; + com::SafeArray <MediumFormatCapabilities_T> mediumFormatCap; + CHECK_ERROR(mediumFormats[i], + COMGETTER(Capabilities)(ComSafeArrayAsOutParam(mediumFormatCap))); + for (ULONG j = 0; j < mediumFormatCap.size(); j++) + caps |= mediumFormatCap[j]; + + + RTPrintf(List::tr("Backend %u: id='%ls' description='%ls' capabilities=%#06x extensions='"), + i, id.raw(), description.raw(), caps); + + /* File extensions */ + com::SafeArray<BSTR> fileExtensions; + com::SafeArray<DeviceType_T> deviceTypes; + CHECK_ERROR(mediumFormats[i], + DescribeFileExtensions(ComSafeArrayAsOutParam(fileExtensions), ComSafeArrayAsOutParam(deviceTypes))); + for (size_t j = 0; j < fileExtensions.size(); ++j) + { + RTPrintf("%ls (%s)", Bstr(fileExtensions[j]).raw(), getDeviceTypeText(deviceTypes[j])); + if (j != fileExtensions.size()-1) + RTPrintf(","); + } + RTPrintf("'"); + + /* Configuration keys */ + com::SafeArray<BSTR> propertyNames; + com::SafeArray<BSTR> propertyDescriptions; + com::SafeArray<DataType_T> propertyTypes; + com::SafeArray<ULONG> propertyFlags; + com::SafeArray<BSTR> propertyDefaults; + CHECK_ERROR(mediumFormats[i], + DescribeProperties(ComSafeArrayAsOutParam(propertyNames), + ComSafeArrayAsOutParam(propertyDescriptions), + ComSafeArrayAsOutParam(propertyTypes), + ComSafeArrayAsOutParam(propertyFlags), + ComSafeArrayAsOutParam(propertyDefaults))); + + RTPrintf(List::tr(" properties=(")); + if (propertyNames.size() > 0) + { + for (size_t j = 0; j < propertyNames.size(); ++j) + { + RTPrintf(List::tr("\n name='%ls' desc='%ls' type="), + Bstr(propertyNames[j]).raw(), Bstr(propertyDescriptions[j]).raw()); + switch (propertyTypes[j]) + { + case DataType_Int32: RTPrintf(List::tr("int")); break; + case DataType_Int8: RTPrintf(List::tr("byte")); break; + case DataType_String: RTPrintf(List::tr("string")); break; +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case DataType_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + RTPrintf(List::tr(" flags=%#04x"), propertyFlags[j]); + RTPrintf(List::tr(" default='%ls'"), Bstr(propertyDefaults[j]).raw()); + if (j != propertyNames.size()-1) + RTPrintf(", "); + } + } + RTPrintf(")\n"); + } + return hrc; +} + + +/** + * List USB devices attached to the host. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listUsbHost(const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc; + ComPtr<IHost> Host; + CHECK_ERROR_RET(pVirtualBox, COMGETTER(Host)(Host.asOutParam()), 1); + + SafeIfaceArray<IHostUSBDevice> CollPtr; + CHECK_ERROR_RET(Host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(CollPtr)), 1); + + RTPrintf(List::tr("Host USB Devices:\n\n")); + + if (CollPtr.size() == 0) + { + RTPrintf(List::tr("<none>\n\n")); + } + else + { + for (size_t i = 0; i < CollPtr.size(); ++i) + { + ComPtr<IHostUSBDevice> dev = CollPtr[i]; + + /* Query info. */ + Bstr id; + CHECK_ERROR_RET(dev, COMGETTER(Id)(id.asOutParam()), 1); + USHORT usVendorId; + CHECK_ERROR_RET(dev, COMGETTER(VendorId)(&usVendorId), 1); + USHORT usProductId; + CHECK_ERROR_RET(dev, COMGETTER(ProductId)(&usProductId), 1); + USHORT bcdRevision; + CHECK_ERROR_RET(dev, COMGETTER(Revision)(&bcdRevision), 1); + USHORT usPort; + CHECK_ERROR_RET(dev, COMGETTER(Port)(&usPort), 1); + USHORT usVersion; + CHECK_ERROR_RET(dev, COMGETTER(Version)(&usVersion), 1); + USBConnectionSpeed_T enmSpeed; + CHECK_ERROR_RET(dev, COMGETTER(Speed)(&enmSpeed), 1); + + RTPrintf(List::tr( + "UUID: %s\n" + "VendorId: %#06x (%04X)\n" + "ProductId: %#06x (%04X)\n" + "Revision: %u.%u (%02u%02u)\n" + "Port: %u\n"), + Utf8Str(id).c_str(), + usVendorId, usVendorId, usProductId, usProductId, + bcdRevision >> 8, bcdRevision & 0xff, + bcdRevision >> 8, bcdRevision & 0xff, + usPort); + + const char *pszSpeed = "?"; + switch (enmSpeed) + { + case USBConnectionSpeed_Low: + pszSpeed = List::tr("Low"); + break; + case USBConnectionSpeed_Full: + pszSpeed = List::tr("Full"); + break; + case USBConnectionSpeed_High: + pszSpeed = List::tr("High"); + break; + case USBConnectionSpeed_Super: + pszSpeed = List::tr("Super"); + break; + case USBConnectionSpeed_SuperPlus: + pszSpeed = List::tr("SuperPlus"); + break; + default: + ASSERT(false); + break; + } + + RTPrintf(List::tr("USB version/speed: %u/%s\n"), usVersion, pszSpeed); + + /* optional stuff. */ + SafeArray<BSTR> CollDevInfo; + Bstr bstr; + CHECK_ERROR_RET(dev, COMGETTER(DeviceInfo)(ComSafeArrayAsOutParam(CollDevInfo)), 1); + if (CollDevInfo.size() >= 1) + bstr = Bstr(CollDevInfo[0]); + if (!bstr.isEmpty()) + RTPrintf(List::tr("Manufacturer: %ls\n"), bstr.raw()); + if (CollDevInfo.size() >= 2) + bstr = Bstr(CollDevInfo[1]); + if (!bstr.isEmpty()) + RTPrintf(List::tr("Product: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(dev, COMGETTER(SerialNumber)(bstr.asOutParam()), 1); + if (!bstr.isEmpty()) + RTPrintf(List::tr("SerialNumber: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(dev, COMGETTER(Address)(bstr.asOutParam()), 1); + if (!bstr.isEmpty()) + RTPrintf(List::tr("Address: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(dev, COMGETTER(PortPath)(bstr.asOutParam()), 1); + if (!bstr.isEmpty()) + RTPrintf(List::tr("Port path: %ls\n"), bstr.raw()); + + /* current state */ + USBDeviceState_T state; + CHECK_ERROR_RET(dev, COMGETTER(State)(&state), 1); + const char *pszState = "?"; + switch (state) + { + case USBDeviceState_NotSupported: + pszState = List::tr("Not supported"); + break; + case USBDeviceState_Unavailable: + pszState = List::tr("Unavailable"); + break; + case USBDeviceState_Busy: + pszState = List::tr("Busy"); + break; + case USBDeviceState_Available: + pszState = List::tr("Available"); + break; + case USBDeviceState_Held: + pszState = List::tr("Held"); + break; + case USBDeviceState_Captured: + pszState = List::tr("Captured"); + break; + default: + ASSERT(false); + break; + } + RTPrintf(List::tr("Current State: %s\n\n"), pszState); + } + } + return hrc; +} + + +/** + * List USB filters. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listUsbFilters(const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc; + + RTPrintf(List::tr("Global USB Device Filters:\n\n")); + + ComPtr<IHost> host; + CHECK_ERROR_RET(pVirtualBox, COMGETTER(Host)(host.asOutParam()), 1); + + SafeIfaceArray<IHostUSBDeviceFilter> coll; + CHECK_ERROR_RET(host, COMGETTER(USBDeviceFilters)(ComSafeArrayAsOutParam(coll)), 1); + + if (coll.size() == 0) + { + RTPrintf(List::tr("<none>\n\n")); + } + else + { + for (size_t index = 0; index < coll.size(); ++index) + { + ComPtr<IHostUSBDeviceFilter> flt = coll[index]; + + /* Query info. */ + + RTPrintf(List::tr("Index: %zu\n"), index); + + BOOL active = FALSE; + CHECK_ERROR_RET(flt, COMGETTER(Active)(&active), 1); + RTPrintf(List::tr("Active: %s\n"), active ? List::tr("yes") : List::tr("no")); + + USBDeviceFilterAction_T action; + CHECK_ERROR_RET(flt, COMGETTER(Action)(&action), 1); + const char *pszAction = List::tr("<invalid>"); + switch (action) + { + case USBDeviceFilterAction_Ignore: + pszAction = List::tr("Ignore"); + break; + case USBDeviceFilterAction_Hold: + pszAction = List::tr("Hold"); + break; + default: + break; + } + RTPrintf(List::tr("Action: %s\n"), pszAction); + + Bstr bstr; + CHECK_ERROR_RET(flt, COMGETTER(Name)(bstr.asOutParam()), 1); + RTPrintf(List::tr("Name: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(VendorId)(bstr.asOutParam()), 1); + RTPrintf(List::tr("VendorId: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(ProductId)(bstr.asOutParam()), 1); + RTPrintf(List::tr("ProductId: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(Revision)(bstr.asOutParam()), 1); + RTPrintf(List::tr("Revision: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(Manufacturer)(bstr.asOutParam()), 1); + RTPrintf(List::tr("Manufacturer: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(Product)(bstr.asOutParam()), 1); + RTPrintf(List::tr("Product: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(SerialNumber)(bstr.asOutParam()), 1); + RTPrintf(List::tr("Serial Number: %ls\n"), bstr.raw()); + CHECK_ERROR_RET(flt, COMGETTER(Port)(bstr.asOutParam()), 1); + RTPrintf(List::tr("Port: %ls\n\n"), bstr.raw()); + } + } + return hrc; +} + + +/** + * List system properties. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listSystemProperties(const ComPtr<IVirtualBox> &pVirtualBox) +{ + ComPtr<ISystemProperties> systemProperties; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), hrcCheck); + + Bstr str; + ULONG ulValue; + LONG64 i64Value; + BOOL fValue; + const char *psz; + + pVirtualBox->COMGETTER(APIVersion)(str.asOutParam()); + RTPrintf(List::tr("API version: %ls\n"), str.raw()); + + systemProperties->COMGETTER(MinGuestRAM)(&ulValue); + RTPrintf(List::tr("Minimum guest RAM size: %u Megabytes\n", "", ulValue), ulValue); + systemProperties->COMGETTER(MaxGuestRAM)(&ulValue); + RTPrintf(List::tr("Maximum guest RAM size: %u Megabytes\n", "", ulValue), ulValue); + systemProperties->COMGETTER(MinGuestVRAM)(&ulValue); + RTPrintf(List::tr("Minimum video RAM size: %u Megabytes\n", "", ulValue), ulValue); + systemProperties->COMGETTER(MaxGuestVRAM)(&ulValue); + RTPrintf(List::tr("Maximum video RAM size: %u Megabytes\n", "", ulValue), ulValue); + systemProperties->COMGETTER(MaxGuestMonitors)(&ulValue); + RTPrintf(List::tr("Maximum guest monitor count: %u\n"), ulValue); + systemProperties->COMGETTER(MinGuestCPUCount)(&ulValue); + RTPrintf(List::tr("Minimum guest CPU count: %u\n"), ulValue); + systemProperties->COMGETTER(MaxGuestCPUCount)(&ulValue); + RTPrintf(List::tr("Maximum guest CPU count: %u\n"), ulValue); + systemProperties->COMGETTER(InfoVDSize)(&i64Value); + RTPrintf(List::tr("Virtual disk limit (info): %lld Bytes\n", "" , i64Value), i64Value); + systemProperties->COMGETTER(SerialPortCount)(&ulValue); + RTPrintf(List::tr("Maximum Serial Port count: %u\n"), ulValue); + systemProperties->COMGETTER(ParallelPortCount)(&ulValue); + RTPrintf(List::tr("Maximum Parallel Port count: %u\n"), ulValue); + systemProperties->COMGETTER(MaxBootPosition)(&ulValue); + RTPrintf(List::tr("Maximum Boot Position: %u\n"), ulValue); + systemProperties->GetMaxNetworkAdapters(ChipsetType_PIIX3, &ulValue); + RTPrintf(List::tr("Maximum PIIX3 Network Adapter count: %u\n"), ulValue); + systemProperties->GetMaxNetworkAdapters(ChipsetType_ICH9, &ulValue); + RTPrintf(List::tr("Maximum ICH9 Network Adapter count: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_IDE, &ulValue); + RTPrintf(List::tr("Maximum PIIX3 IDE Controllers: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_IDE, &ulValue); + RTPrintf(List::tr("Maximum ICH9 IDE Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_IDE, &ulValue); + RTPrintf(List::tr("Maximum IDE Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_IDE, &ulValue); + RTPrintf(List::tr("Maximum Devices per IDE Port: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_SATA, &ulValue); + RTPrintf(List::tr("Maximum PIIX3 SATA Controllers: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_SATA, &ulValue); + RTPrintf(List::tr("Maximum ICH9 SATA Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_SATA, &ulValue); + RTPrintf(List::tr("Maximum SATA Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_SATA, &ulValue); + RTPrintf(List::tr("Maximum Devices per SATA Port: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_SCSI, &ulValue); + RTPrintf(List::tr("Maximum PIIX3 SCSI Controllers: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_SCSI, &ulValue); + RTPrintf(List::tr("Maximum ICH9 SCSI Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_SCSI, &ulValue); + RTPrintf(List::tr("Maximum SCSI Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_SCSI, &ulValue); + RTPrintf(List::tr("Maximum Devices per SCSI Port: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_SAS, &ulValue); + RTPrintf(List::tr("Maximum SAS PIIX3 Controllers: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_SAS, &ulValue); + RTPrintf(List::tr("Maximum SAS ICH9 Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_SAS, &ulValue); + RTPrintf(List::tr("Maximum SAS Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_SAS, &ulValue); + RTPrintf(List::tr("Maximum Devices per SAS Port: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_PCIe, &ulValue); + RTPrintf(List::tr("Maximum NVMe PIIX3 Controllers: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_PCIe, &ulValue); + RTPrintf(List::tr("Maximum NVMe ICH9 Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_PCIe, &ulValue); + RTPrintf(List::tr("Maximum NVMe Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_PCIe, &ulValue); + RTPrintf(List::tr("Maximum Devices per NVMe Port: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_VirtioSCSI, &ulValue); + RTPrintf(List::tr("Maximum virtio-scsi PIIX3 Controllers: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_VirtioSCSI, &ulValue); + RTPrintf(List::tr("Maximum virtio-scsi ICH9 Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_VirtioSCSI, &ulValue); + RTPrintf(List::tr("Maximum virtio-scsi Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_VirtioSCSI, &ulValue); + RTPrintf(List::tr("Maximum Devices per virtio-scsi Port: %u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_PIIX3, StorageBus_Floppy, &ulValue); + RTPrintf(List::tr("Maximum PIIX3 Floppy Controllers:%u\n"), ulValue); + systemProperties->GetMaxInstancesOfStorageBus(ChipsetType_ICH9, StorageBus_Floppy, &ulValue); + RTPrintf(List::tr("Maximum ICH9 Floppy Controllers: %u\n"), ulValue); + systemProperties->GetMaxPortCountForStorageBus(StorageBus_Floppy, &ulValue); + RTPrintf(List::tr("Maximum Floppy Port count: %u\n"), ulValue); + systemProperties->GetMaxDevicesPerPortForStorageBus(StorageBus_Floppy, &ulValue); + RTPrintf(List::tr("Maximum Devices per Floppy Port: %u\n"), ulValue); +#if 0 + systemProperties->GetFreeDiskSpaceWarning(&i64Value); + RTPrintf(List::tr("Free disk space warning at: %u Bytes\n", "", i64Value), i64Value); + systemProperties->GetFreeDiskSpacePercentWarning(&ulValue); + RTPrintf(List::tr("Free disk space warning at: %u %%\n"), ulValue); + systemProperties->GetFreeDiskSpaceError(&i64Value); + RTPrintf(List::tr("Free disk space error at: %u Bytes\n", "", i64Value), i64Value); + systemProperties->GetFreeDiskSpacePercentError(&ulValue); + RTPrintf(List::tr("Free disk space error at: %u %%\n"), ulValue); +#endif + systemProperties->COMGETTER(DefaultMachineFolder)(str.asOutParam()); + RTPrintf(List::tr("Default machine folder: %ls\n"), str.raw()); + systemProperties->COMGETTER(RawModeSupported)(&fValue); + RTPrintf(List::tr("Raw-mode Supported: %s\n"), fValue ? List::tr("yes") : List::tr("no")); + systemProperties->COMGETTER(ExclusiveHwVirt)(&fValue); + RTPrintf(List::tr("Exclusive HW virtualization use: %s\n"), fValue ? List::tr("on") : List::tr("off")); + systemProperties->COMGETTER(DefaultHardDiskFormat)(str.asOutParam()); + RTPrintf(List::tr("Default hard disk format: %ls\n"), str.raw()); + systemProperties->COMGETTER(VRDEAuthLibrary)(str.asOutParam()); + RTPrintf(List::tr("VRDE auth library: %ls\n"), str.raw()); + systemProperties->COMGETTER(WebServiceAuthLibrary)(str.asOutParam()); + RTPrintf(List::tr("Webservice auth. library: %ls\n"), str.raw()); + systemProperties->COMGETTER(DefaultVRDEExtPack)(str.asOutParam()); + RTPrintf(List::tr("Remote desktop ExtPack: %ls\n"), str.raw()); + systemProperties->COMGETTER(DefaultCryptoExtPack)(str.asOutParam()); + RTPrintf(List::tr("VM encryption ExtPack: %ls\n"), str.raw()); + systemProperties->COMGETTER(LogHistoryCount)(&ulValue); + RTPrintf(List::tr("Log history count: %u\n"), ulValue); + systemProperties->COMGETTER(DefaultFrontend)(str.asOutParam()); + RTPrintf(List::tr("Default frontend: %ls\n"), str.raw()); + AudioDriverType_T enmAudio; + systemProperties->COMGETTER(DefaultAudioDriver)(&enmAudio); + switch (enmAudio) + { + case AudioDriverType_Default: psz = List::tr("Default"); break; + case AudioDriverType_Null: psz = List::tr("Null"); break; + case AudioDriverType_OSS: psz = "OSS"; break; + case AudioDriverType_ALSA: psz = "ALSA"; break; + case AudioDriverType_Pulse: psz = "PulseAudio"; break; + case AudioDriverType_WinMM: psz = "WinMM"; break; + case AudioDriverType_DirectSound: psz = "DirectSound"; break; + case AudioDriverType_WAS: psz = "Windows Audio Session"; break; + case AudioDriverType_CoreAudio: psz = "CoreAudio"; break; + case AudioDriverType_SolAudio: psz = "SolAudio"; break; + case AudioDriverType_MMPM: psz = "MMPM"; break; + default: psz = List::tr("Unknown"); + } + RTPrintf(List::tr("Default audio driver: %s\n"), psz); + systemProperties->COMGETTER(AutostartDatabasePath)(str.asOutParam()); + RTPrintf(List::tr("Autostart database path: %ls\n"), str.raw()); + systemProperties->COMGETTER(DefaultAdditionsISO)(str.asOutParam()); + RTPrintf(List::tr("Default Guest Additions ISO: %ls\n"), str.raw()); + systemProperties->COMGETTER(LoggingLevel)(str.asOutParam()); + RTPrintf(List::tr("Logging Level: %ls\n"), str.raw()); + ProxyMode_T enmProxyMode = (ProxyMode_T)42; + systemProperties->COMGETTER(ProxyMode)(&enmProxyMode); + psz = List::tr("Unknown"); + switch (enmProxyMode) + { + case ProxyMode_System: psz = List::tr("System"); break; + case ProxyMode_NoProxy: psz = List::tr("NoProxy"); break; + case ProxyMode_Manual: psz = List::tr("Manual"); break; +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case ProxyMode_32BitHack: break; /* Shut up compiler warnings. */ +#endif + } + RTPrintf(List::tr("Proxy Mode: %s\n"), psz); + systemProperties->COMGETTER(ProxyURL)(str.asOutParam()); + RTPrintf(List::tr("Proxy URL: %ls\n"), str.raw()); +#ifdef VBOX_WITH_MAIN_NLS + systemProperties->COMGETTER(LanguageId)(str.asOutParam()); + RTPrintf(List::tr("User language: %ls\n"), str.raw()); +#endif + return S_OK; +} + +#ifdef VBOX_WITH_UPDATE_AGENT +static HRESULT listUpdateAgentConfig(ComPtr<IUpdateAgent> ptrUpdateAgent) +{ + BOOL fValue; + ptrUpdateAgent->COMGETTER(Enabled)(&fValue); + RTPrintf(List::tr("Enabled: %s\n"), fValue ? List::tr("yes") : List::tr("no")); + ULONG ulValue; + ptrUpdateAgent->COMGETTER(CheckCount)(&ulValue); + RTPrintf(List::tr("Check count: %u\n"), ulValue); + ptrUpdateAgent->COMGETTER(CheckFrequency)(&ulValue); + if (ulValue == 0) + RTPrintf(List::tr("Check frequency: never\n")); + else if (ulValue == 1) + RTPrintf(List::tr("Check frequency: every day\n")); + else + RTPrintf(List::tr("Check frequency: every %u days\n", "", ulValue), ulValue); + + Bstr str; + const char *psz; + UpdateChannel_T enmUpdateChannel; + ptrUpdateAgent->COMGETTER(Channel)(&enmUpdateChannel); + switch (enmUpdateChannel) + { + case UpdateChannel_Stable: + psz = List::tr("Stable: Maintenance and minor releases within the same major release"); + break; + case UpdateChannel_All: + psz = List::tr("All releases: All stable releases, including major versions"); + break; + case UpdateChannel_WithBetas: + psz = List::tr("With Betas: All stable and major releases, including beta versions"); + break; + case UpdateChannel_WithTesting: + psz = List::tr("With Testing: All stable, major and beta releases, including testing versions"); + break; + default: + psz = List::tr("Unset"); + break; + } + RTPrintf(List::tr("Channel: %s\n"), psz); + ptrUpdateAgent->COMGETTER(RepositoryURL)(str.asOutParam()); + RTPrintf(List::tr("Repository: %ls\n"), str.raw()); + ptrUpdateAgent->COMGETTER(LastCheckDate)(str.asOutParam()); + RTPrintf(List::tr("Last check date: %ls\n"), str.raw()); + + return S_OK; +} + +static HRESULT listUpdateAgents(const ComPtr<IVirtualBox> &pVirtualBox) +{ + ComPtr<IHost> pHost; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(Host)(pHost.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IUpdateAgent> pUpdateHost; + CHECK_ERROR2I_RET(pHost, COMGETTER(UpdateHost)(pUpdateHost.asOutParam()), RTEXITCODE_FAILURE); + /** @todo Add other update agents here. */ + + return listUpdateAgentConfig(pUpdateHost); +} +#endif /* VBOX_WITH_UPDATE_AGENT */ + +/** + * Helper for listDhcpServers() that shows a DHCP configuration. + */ +static HRESULT showDhcpConfig(ComPtr<IDHCPConfig> ptrConfig) +{ + HRESULT hrcRet = S_OK; + + ULONG secs = 0; + CHECK_ERROR2I_STMT(ptrConfig, COMGETTER(MinLeaseTime)(&secs), hrcRet = hrcCheck); + if (secs == 0) + RTPrintf(List::tr(" minLeaseTime: default\n")); + else + RTPrintf(List::tr(" minLeaseTime: %u sec\n"), secs); + + secs = 0; + CHECK_ERROR2I_STMT(ptrConfig, COMGETTER(DefaultLeaseTime)(&secs), hrcRet = hrcCheck); + if (secs == 0) + RTPrintf(List::tr(" defaultLeaseTime: default\n")); + else + RTPrintf(List::tr(" defaultLeaseTime: %u sec\n"), secs); + + secs = 0; + CHECK_ERROR2I_STMT(ptrConfig, COMGETTER(MaxLeaseTime)(&secs), hrcRet = hrcCheck); + if (secs == 0) + RTPrintf(List::tr(" maxLeaseTime: default\n")); + else + RTPrintf(List::tr(" maxLeaseTime: %u sec\n"), secs); + + com::SafeArray<DHCPOption_T> Options; + HRESULT hrc; + CHECK_ERROR2_STMT(hrc, ptrConfig, COMGETTER(ForcedOptions(ComSafeArrayAsOutParam(Options))), hrcRet = hrc); + if (FAILED(hrc)) + RTPrintf(List::tr(" Forced options: %Rhrc\n"), hrc); + else if (Options.size() == 0) + RTPrintf(List::tr(" Forced options: None\n")); + else + { + RTPrintf(List::tr(" Forced options: ")); + for (size_t i = 0; i < Options.size(); i++) + RTPrintf(i ? ", %u" : "%u", Options[i]); + RTPrintf("\n"); + } + + CHECK_ERROR2_STMT(hrc, ptrConfig, COMGETTER(SuppressedOptions(ComSafeArrayAsOutParam(Options))), hrcRet = hrc); + if (FAILED(hrc)) + RTPrintf(List::tr(" Suppressed opt.s: %Rhrc\n"), hrc); + else if (Options.size() == 0) + RTPrintf(List::tr(" Suppressed opts.: None\n")); + else + { + RTPrintf(List::tr(" Suppressed opts.: ")); + for (size_t i = 0; i < Options.size(); i++) + RTPrintf(i ? ", %u" : "%u", Options[i]); + RTPrintf("\n"); + } + + com::SafeArray<DHCPOptionEncoding_T> Encodings; + com::SafeArray<BSTR> Values; + CHECK_ERROR2_STMT(hrc, ptrConfig, GetAllOptions(ComSafeArrayAsOutParam(Options), + ComSafeArrayAsOutParam(Encodings), + ComSafeArrayAsOutParam(Values)), hrcRet = hrc); + if (FAILED(hrc)) + RTPrintf(List::tr(" DHCP options: %Rhrc\n"), hrc); + else if (Options.size() != Encodings.size() || Options.size() != Values.size()) + { + RTPrintf(List::tr(" DHCP options: Return count mismatch: %zu, %zu, %zu\n"), + Options.size(), Encodings.size(), Values.size()); + hrcRet = E_FAIL; + } + else if (Options.size() == 0) + RTPrintf(List::tr(" DHCP options: None\n")); + else + for (size_t i = 0; i < Options.size(); i++) + { + switch (Encodings[i]) + { + case DHCPOptionEncoding_Normal: + RTPrintf(List::tr(" %3d/legacy: %ls\n"), Options[i], Values[i]); + break; + case DHCPOptionEncoding_Hex: + RTPrintf(" %3d/hex: %ls\n", Options[i], Values[i]); + break; + default: + RTPrintf(" %3d/%u?: %ls\n", Options[i], Encodings[i], Values[i]); + break; + } + } + + return S_OK; +} + + +/** + * List DHCP servers. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listDhcpServers(const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrcRet = S_OK; + com::SafeIfaceArray<IDHCPServer> DHCPServers; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(DHCPServers)(ComSafeArrayAsOutParam(DHCPServers)), hrcCheck); + for (size_t i = 0; i < DHCPServers.size(); ++i) + { + if (i > 0) + RTPrintf("\n"); + + ComPtr<IDHCPServer> ptrDHCPServer = DHCPServers[i]; + Bstr bstr; + CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(NetworkName)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf(List::tr("NetworkName: %ls\n"), bstr.raw()); + + CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(IPAddress)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf("Dhcpd IP: %ls\n", bstr.raw()); + + CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(LowerIP)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf(List::tr("LowerIPAddress: %ls\n"), bstr.raw()); + + CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(UpperIP)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf(List::tr("UpperIPAddress: %ls\n"), bstr.raw()); + + CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(NetworkMask)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf(List::tr("NetworkMask: %ls\n"), bstr.raw()); + + BOOL fEnabled = FALSE; + CHECK_ERROR2I_STMT(ptrDHCPServer, COMGETTER(Enabled)(&fEnabled), hrcRet = hrcCheck); + RTPrintf(List::tr("Enabled: %s\n"), fEnabled ? List::tr("Yes") : List::tr("No")); + + /* Global configuration: */ + RTPrintf(List::tr("Global Configuration:\n")); + HRESULT hrc; + ComPtr<IDHCPGlobalConfig> ptrGlobal; + CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(GlobalConfig)(ptrGlobal.asOutParam()), hrcRet = hrc); + if (SUCCEEDED(hrc)) + { + hrc = showDhcpConfig(ptrGlobal); + if (FAILED(hrc)) + hrcRet = hrc; + } + + /* Group configurations: */ + com::SafeIfaceArray<IDHCPGroupConfig> Groups; + CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(GroupConfigs)(ComSafeArrayAsOutParam(Groups)), hrcRet = hrc); + if (FAILED(hrc)) + RTPrintf(List::tr("Groups: %Rrc\n"), hrc); + else if (Groups.size() == 0) + RTPrintf(List::tr("Groups: None\n")); + else + { + for (size_t iGrp = 0; iGrp < Groups.size(); iGrp++) + { + CHECK_ERROR2I_STMT(Groups[iGrp], COMGETTER(Name)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf(List::tr("Group: %ls\n"), bstr.raw()); + + com::SafeIfaceArray<IDHCPGroupCondition> Conditions; + CHECK_ERROR2_STMT(hrc, Groups[iGrp], COMGETTER(Conditions)(ComSafeArrayAsOutParam(Conditions)), hrcRet = hrc); + if (FAILED(hrc)) + RTPrintf(List::tr(" Conditions: %Rhrc\n"), hrc); + else if (Conditions.size() == 0) + RTPrintf(List::tr(" Conditions: None\n")); + else + for (size_t iCond = 0; iCond < Conditions.size(); iCond++) + { + BOOL fInclusive = TRUE; + CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Inclusive)(&fInclusive), hrcRet = hrc); + DHCPGroupConditionType_T enmType = DHCPGroupConditionType_MAC; + CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Type)(&enmType), hrcRet = hrc); + CHECK_ERROR2_STMT(hrc, Conditions[iCond], COMGETTER(Value)(bstr.asOutParam()), hrcRet = hrc); + + RTPrintf(List::tr(" Conditions: %s %s %ls\n"), + fInclusive ? List::tr("include") : List::tr("exclude"), + enmType == DHCPGroupConditionType_MAC ? "MAC " + : enmType == DHCPGroupConditionType_MACWildcard ? "MAC* " + : enmType == DHCPGroupConditionType_vendorClassID ? "VendorCID " + : enmType == DHCPGroupConditionType_vendorClassIDWildcard ? "VendorCID*" + : enmType == DHCPGroupConditionType_userClassID ? "UserCID " + : enmType == DHCPGroupConditionType_userClassIDWildcard ? "UserCID* " + : "!UNKNOWN! ", + bstr.raw()); + } + + hrc = showDhcpConfig(Groups[iGrp]); + if (FAILED(hrc)) + hrcRet = hrc; + } + Groups.setNull(); + } + + /* Individual host / NIC configurations: */ + com::SafeIfaceArray<IDHCPIndividualConfig> Hosts; + CHECK_ERROR2_STMT(hrc, ptrDHCPServer, COMGETTER(IndividualConfigs)(ComSafeArrayAsOutParam(Hosts)), hrcRet = hrc); + if (FAILED(hrc)) + RTPrintf(List::tr("Individual Configs: %Rrc\n"), hrc); + else if (Hosts.size() == 0) + RTPrintf(List::tr("Individual Configs: None\n")); + else + { + for (size_t iHost = 0; iHost < Hosts.size(); iHost++) + { + DHCPConfigScope_T enmScope = DHCPConfigScope_MAC; + CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(Scope)(&enmScope), hrcRet = hrcCheck); + + if (enmScope == DHCPConfigScope_MAC) + { + CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(MACAddress)(bstr.asOutParam()), hrcRet = hrcCheck); + RTPrintf(List::tr("Individual Config: MAC %ls\n"), bstr.raw()); + } + else + { + ULONG uSlot = 0; + CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(Slot)(&uSlot), hrcRet = hrcCheck); + CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(MachineId)(bstr.asOutParam()), hrcRet = hrcCheck); + Bstr bstrMACAddress; + hrc = Hosts[iHost]->COMGETTER(MACAddress)(bstrMACAddress.asOutParam()); /* No CHECK_ERROR2 stuff! */ + if (SUCCEEDED(hrc)) + RTPrintf(List::tr("Individual Config: VM NIC: %ls slot %u, MAC %ls\n"), bstr.raw(), uSlot, + bstrMACAddress.raw()); + else + RTPrintf(List::tr("Individual Config: VM NIC: %ls slot %u, MAC %Rhrc\n"), bstr.raw(), uSlot, hrc); + } + + CHECK_ERROR2I_STMT(Hosts[iHost], COMGETTER(FixedAddress)(bstr.asOutParam()), hrcRet = hrcCheck); + if (bstr.isNotEmpty()) + RTPrintf(List::tr(" Fixed Address: %ls\n"), bstr.raw()); + else + RTPrintf(List::tr(" Fixed Address: dynamic\n")); + + hrc = showDhcpConfig(Hosts[iHost]); + if (FAILED(hrc)) + hrcRet = hrc; + } + Hosts.setNull(); + } + } + + return hrcRet; +} + +/** + * List extension packs. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listExtensionPacks(const ComPtr<IVirtualBox> &pVirtualBox) +{ + ComObjPtr<IExtPackManager> ptrExtPackMgr; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(ExtensionPackManager)(ptrExtPackMgr.asOutParam()), hrcCheck); + + SafeIfaceArray<IExtPack> extPacks; + CHECK_ERROR2I_RET(ptrExtPackMgr, COMGETTER(InstalledExtPacks)(ComSafeArrayAsOutParam(extPacks)), hrcCheck); + RTPrintf(List::tr("Extension Packs: %u\n"), extPacks.size()); + + HRESULT hrc = S_OK; + for (size_t i = 0; i < extPacks.size(); i++) + { + /* Read all the properties. */ + Bstr bstrName; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(Name)(bstrName.asOutParam()), hrc = hrcCheck; bstrName.setNull()); + Bstr bstrDesc; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(Description)(bstrDesc.asOutParam()), hrc = hrcCheck; bstrDesc.setNull()); + Bstr bstrVersion; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(Version)(bstrVersion.asOutParam()), hrc = hrcCheck; bstrVersion.setNull()); + ULONG uRevision; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(Revision)(&uRevision), hrc = hrcCheck; uRevision = 0); + Bstr bstrEdition; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(Edition)(bstrEdition.asOutParam()), hrc = hrcCheck; bstrEdition.setNull()); + Bstr bstrVrdeModule; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(VRDEModule)(bstrVrdeModule.asOutParam()),hrc=hrcCheck; bstrVrdeModule.setNull()); + Bstr bstrCryptoModule; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(CryptoModule)(bstrCryptoModule.asOutParam()),hrc=hrcCheck; bstrCryptoModule.setNull()); + BOOL fUsable; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(Usable)(&fUsable), hrc = hrcCheck; fUsable = FALSE); + Bstr bstrWhy; + CHECK_ERROR2I_STMT(extPacks[i], COMGETTER(WhyUnusable)(bstrWhy.asOutParam()), hrc = hrcCheck; bstrWhy.setNull()); + + /* Display them. */ + if (i) + RTPrintf("\n"); + RTPrintf(List::tr( + "Pack no.%2zu: %ls\n" + "Version: %ls\n" + "Revision: %u\n" + "Edition: %ls\n" + "Description: %ls\n" + "VRDE Module: %ls\n" + "Crypto Module: %ls\n" + "Usable: %RTbool\n" + "Why unusable: %ls\n"), + i, bstrName.raw(), + bstrVersion.raw(), + uRevision, + bstrEdition.raw(), + bstrDesc.raw(), + bstrVrdeModule.raw(), + bstrCryptoModule.raw(), + fUsable != FALSE, + bstrWhy.raw()); + + /* Query plugins and display them. */ + } + return hrc; +} + + +/** + * List machine groups. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT listGroups(const ComPtr<IVirtualBox> &pVirtualBox) +{ + SafeArray<BSTR> groups; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(MachineGroups)(ComSafeArrayAsOutParam(groups)), hrcCheck); + + for (size_t i = 0; i < groups.size(); i++) + { + RTPrintf("\"%ls\"\n", groups[i]); + } + return S_OK; +} + + +/** + * List video capture devices. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox pointer. + */ +static HRESULT listVideoInputDevices(const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc; + ComPtr<IHost> host; + CHECK_ERROR(pVirtualBox, COMGETTER(Host)(host.asOutParam())); + com::SafeIfaceArray<IHostVideoInputDevice> hostVideoInputDevices; + CHECK_ERROR(host, COMGETTER(VideoInputDevices)(ComSafeArrayAsOutParam(hostVideoInputDevices))); + RTPrintf(List::tr("Video Input Devices: %u\n"), hostVideoInputDevices.size()); + for (size_t i = 0; i < hostVideoInputDevices.size(); ++i) + { + ComPtr<IHostVideoInputDevice> p = hostVideoInputDevices[i]; + Bstr name; + p->COMGETTER(Name)(name.asOutParam()); + Bstr path; + p->COMGETTER(Path)(path.asOutParam()); + Bstr alias; + p->COMGETTER(Alias)(alias.asOutParam()); + RTPrintf("%ls \"%ls\"\n%ls\n", alias.raw(), name.raw(), path.raw()); + } + return hrc; +} + +/** + * List supported screen shot formats. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox pointer. + */ +static HRESULT listScreenShotFormats(const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc = S_OK; + ComPtr<ISystemProperties> systemProperties; + CHECK_ERROR(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam())); + com::SafeArray<BitmapFormat_T> formats; + CHECK_ERROR(systemProperties, COMGETTER(ScreenShotFormats)(ComSafeArrayAsOutParam(formats))); + + RTPrintf(List::tr("Supported %d screen shot formats:\n", "", formats.size()), formats.size()); + for (size_t i = 0; i < formats.size(); ++i) + { + uint32_t u32Format = (uint32_t)formats[i]; + char szFormat[5]; + szFormat[0] = RT_BYTE1(u32Format); + szFormat[1] = RT_BYTE2(u32Format); + szFormat[2] = RT_BYTE3(u32Format); + szFormat[3] = RT_BYTE4(u32Format); + szFormat[4] = 0; + RTPrintf(" BitmapFormat_%s (0x%08X)\n", szFormat, u32Format); + } + return hrc; +} + +/** + * List available cloud providers. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox pointer. + */ +static HRESULT listCloudProviders(const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc = S_OK; + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR(pVirtualBox, COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam())); + com::SafeIfaceArray<ICloudProvider> apCloudProviders; + CHECK_ERROR(pCloudProviderManager, COMGETTER(Providers)(ComSafeArrayAsOutParam(apCloudProviders))); + + RTPrintf(List::tr("Supported %d cloud providers:\n", "", apCloudProviders.size()), apCloudProviders.size()); + for (size_t i = 0; i < apCloudProviders.size(); ++i) + { + ComPtr<ICloudProvider> pCloudProvider = apCloudProviders[i]; + Bstr bstrProviderName; + pCloudProvider->COMGETTER(Name)(bstrProviderName.asOutParam()); + RTPrintf(List::tr("Name: %ls\n"), bstrProviderName.raw()); + pCloudProvider->COMGETTER(ShortName)(bstrProviderName.asOutParam()); + RTPrintf(List::tr("Short Name: %ls\n"), bstrProviderName.raw()); + Bstr bstrProviderID; + pCloudProvider->COMGETTER(Id)(bstrProviderID.asOutParam()); + RTPrintf("GUID: %ls\n", bstrProviderID.raw()); + + RTPrintf("\n"); + } + return hrc; +} + + +/** + * List all available cloud profiles (by iterating over the cloud providers). + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox pointer. + * @param fOptLong If true, list all profile properties. + */ +static HRESULT listCloudProfiles(const ComPtr<IVirtualBox> &pVirtualBox, bool fOptLong) +{ + HRESULT hrc = S_OK; + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR(pVirtualBox, COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam())); + com::SafeIfaceArray<ICloudProvider> apCloudProviders; + CHECK_ERROR(pCloudProviderManager, COMGETTER(Providers)(ComSafeArrayAsOutParam(apCloudProviders))); + + for (size_t i = 0; i < apCloudProviders.size(); ++i) + { + ComPtr<ICloudProvider> pCloudProvider = apCloudProviders[i]; + com::SafeIfaceArray<ICloudProfile> apCloudProfiles; + CHECK_ERROR(pCloudProvider, COMGETTER(Profiles)(ComSafeArrayAsOutParam(apCloudProfiles))); + for (size_t j = 0; j < apCloudProfiles.size(); ++j) + { + ComPtr<ICloudProfile> pCloudProfile = apCloudProfiles[j]; + Bstr bstrProfileName; + pCloudProfile->COMGETTER(Name)(bstrProfileName.asOutParam()); + RTPrintf(List::tr("Name: %ls\n"), bstrProfileName.raw()); + Bstr bstrProviderID; + pCloudProfile->COMGETTER(ProviderId)(bstrProviderID.asOutParam()); + RTPrintf(List::tr("Provider GUID: %ls\n"), bstrProviderID.raw()); + + if (fOptLong) + { + com::SafeArray<BSTR> names; + com::SafeArray<BSTR> values; + pCloudProfile->GetProperties(Bstr().raw(), ComSafeArrayAsOutParam(names), ComSafeArrayAsOutParam(values)); + size_t cNames = names.size(); + size_t cValues = values.size(); + bool fFirst = true; + for (size_t k = 0; k < cNames; k++) + { + Bstr value; + if (k < cValues) + value = values[k]; + RTPrintf("%s%ls=%ls\n", + fFirst ? List::tr("Property: ") : " ", + names[k], value.raw()); + fFirst = false; + } + } + + RTPrintf("\n"); + } + } + return hrc; +} + +static HRESULT displayCPUProfile(ICPUProfile *pProfile, size_t idx, int cchIdx, bool fOptLong, HRESULT hrc) +{ + /* Retrieve the attributes needed for both long and short display. */ + Bstr bstrName; + CHECK_ERROR2I_RET(pProfile, COMGETTER(Name)(bstrName.asOutParam()), hrcCheck); + + CPUArchitecture_T enmArchitecture = CPUArchitecture_Any; + CHECK_ERROR2I_RET(pProfile, COMGETTER(Architecture)(&enmArchitecture), hrcCheck); + const char *pszArchitecture = "???"; + switch (enmArchitecture) + { + case CPUArchitecture_x86: pszArchitecture = "x86"; break; + case CPUArchitecture_AMD64: pszArchitecture = "AMD64"; break; + +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case CPUArchitecture_32BitHack: +#endif + case CPUArchitecture_Any: + break; + } + + /* Print what we've got. */ + if (!fOptLong) + RTPrintf("#%0*zu: %ls [%s]\n", cchIdx, idx, bstrName.raw(), pszArchitecture); + else + { + RTPrintf(List::tr("CPU Profile #%02zu:\n"), idx); + RTPrintf(List::tr(" Architecture: %s\n"), pszArchitecture); + RTPrintf(List::tr(" Name: %ls\n"), bstrName.raw()); + CHECK_ERROR2I_RET(pProfile, COMGETTER(FullName)(bstrName.asOutParam()), hrcCheck); + RTPrintf(List::tr(" Full Name: %ls\n"), bstrName.raw()); + } + return hrc; +} + + +/** + * List all CPU profiles. + * + * @returns See produceList. + * @param ptrVirtualBox Reference to the smart IVirtualBox pointer. + * @param fOptLong If true, list all profile properties. + * @param fOptSorted Sort the output if true, otherwise display in + * system order. + */ +static HRESULT listCPUProfiles(const ComPtr<IVirtualBox> &ptrVirtualBox, bool fOptLong, bool fOptSorted) +{ + ComPtr<ISystemProperties> ptrSysProps; + CHECK_ERROR2I_RET(ptrVirtualBox, COMGETTER(SystemProperties)(ptrSysProps.asOutParam()), hrcCheck); + com::SafeIfaceArray<ICPUProfile> aCPUProfiles; + CHECK_ERROR2I_RET(ptrSysProps, GetCPUProfiles(CPUArchitecture_Any, Bstr().raw(), + ComSafeArrayAsOutParam(aCPUProfiles)), hrcCheck); + + int const cchIdx = 1 + (aCPUProfiles.size() >= 10) + (aCPUProfiles.size() >= 100); + + HRESULT hrc = S_OK; + if (!fOptSorted) + for (size_t i = 0; i < aCPUProfiles.size(); i++) + hrc = displayCPUProfile(aCPUProfiles[i], i, cchIdx, fOptLong, hrc); + else + { + std::vector<std::pair<com::Bstr, ICPUProfile *> > vecSortedProfiles; + for (size_t i = 0; i < aCPUProfiles.size(); ++i) + { + Bstr bstrName; + CHECK_ERROR2I_RET(aCPUProfiles[i], COMGETTER(Name)(bstrName.asOutParam()), hrcCheck); + try + { + vecSortedProfiles.push_back(std::pair<com::Bstr, ICPUProfile *>(bstrName, aCPUProfiles[i])); + } + catch (std::bad_alloc &) + { + return E_OUTOFMEMORY; + } + } + + std::sort(vecSortedProfiles.begin(), vecSortedProfiles.end()); + + for (size_t i = 0; i < vecSortedProfiles.size(); i++) + hrc = displayCPUProfile(vecSortedProfiles[i].second, i, cchIdx, fOptLong, hrc); + } + + return hrc; +} + + +/** + * Translates PartitionType_T to a string if possible. + * @returns read-only string if known value, @a pszUnknown if not. + */ +static const char *PartitionTypeToString(PartitionType_T enmType, const char *pszUnknown) +{ +#define MY_CASE_STR(a_Type) case RT_CONCAT(PartitionType_,a_Type): return #a_Type + switch (enmType) + { + MY_CASE_STR(Empty); + MY_CASE_STR(FAT12); + MY_CASE_STR(FAT16); + MY_CASE_STR(FAT); + MY_CASE_STR(IFS); + MY_CASE_STR(FAT32CHS); + MY_CASE_STR(FAT32LBA); + MY_CASE_STR(FAT16B); + MY_CASE_STR(Extended); + MY_CASE_STR(WindowsRE); + MY_CASE_STR(LinuxSwapOld); + MY_CASE_STR(LinuxOld); + MY_CASE_STR(DragonFlyBSDSlice); + MY_CASE_STR(LinuxSwap); + MY_CASE_STR(Linux); + MY_CASE_STR(LinuxExtended); + MY_CASE_STR(LinuxLVM); + MY_CASE_STR(BSDSlice); + MY_CASE_STR(AppleUFS); + MY_CASE_STR(AppleHFS); + MY_CASE_STR(Solaris); + MY_CASE_STR(GPT); + MY_CASE_STR(EFI); + MY_CASE_STR(Unknown); + MY_CASE_STR(MBR); + MY_CASE_STR(iFFS); + MY_CASE_STR(SonyBoot); + MY_CASE_STR(LenovoBoot); + MY_CASE_STR(WindowsMSR); + MY_CASE_STR(WindowsBasicData); + MY_CASE_STR(WindowsLDMMeta); + MY_CASE_STR(WindowsLDMData); + MY_CASE_STR(WindowsRecovery); + MY_CASE_STR(WindowsStorageSpaces); + MY_CASE_STR(WindowsStorageReplica); + MY_CASE_STR(IBMGPFS); + MY_CASE_STR(LinuxData); + MY_CASE_STR(LinuxRAID); + MY_CASE_STR(LinuxRootX86); + MY_CASE_STR(LinuxRootAMD64); + MY_CASE_STR(LinuxRootARM32); + MY_CASE_STR(LinuxRootARM64); + MY_CASE_STR(LinuxHome); + MY_CASE_STR(LinuxSrv); + MY_CASE_STR(LinuxPlainDmCrypt); + MY_CASE_STR(LinuxLUKS); + MY_CASE_STR(LinuxReserved); + MY_CASE_STR(FreeBSDBoot); + MY_CASE_STR(FreeBSDData); + MY_CASE_STR(FreeBSDSwap); + MY_CASE_STR(FreeBSDUFS); + MY_CASE_STR(FreeBSDVinum); + MY_CASE_STR(FreeBSDZFS); + MY_CASE_STR(FreeBSDUnknown); + MY_CASE_STR(AppleHFSPlus); + MY_CASE_STR(AppleAPFS); + MY_CASE_STR(AppleRAID); + MY_CASE_STR(AppleRAIDOffline); + MY_CASE_STR(AppleBoot); + MY_CASE_STR(AppleLabel); + MY_CASE_STR(AppleTvRecovery); + MY_CASE_STR(AppleCoreStorage); + MY_CASE_STR(SoftRAIDStatus); + MY_CASE_STR(SoftRAIDScratch); + MY_CASE_STR(SoftRAIDVolume); + MY_CASE_STR(SoftRAIDCache); + MY_CASE_STR(AppleUnknown); + MY_CASE_STR(SolarisBoot); + MY_CASE_STR(SolarisRoot); + MY_CASE_STR(SolarisSwap); + MY_CASE_STR(SolarisBackup); + MY_CASE_STR(SolarisUsr); + MY_CASE_STR(SolarisVar); + MY_CASE_STR(SolarisHome); + MY_CASE_STR(SolarisAltSector); + MY_CASE_STR(SolarisReserved); + MY_CASE_STR(SolarisUnknown); + MY_CASE_STR(NetBSDSwap); + MY_CASE_STR(NetBSDFFS); + MY_CASE_STR(NetBSDLFS); + MY_CASE_STR(NetBSDRAID); + MY_CASE_STR(NetBSDConcatenated); + MY_CASE_STR(NetBSDEncrypted); + MY_CASE_STR(NetBSDUnknown); + MY_CASE_STR(ChromeOSKernel); + MY_CASE_STR(ChromeOSRootFS); + MY_CASE_STR(ChromeOSFuture); + MY_CASE_STR(ContLnxUsr); + MY_CASE_STR(ContLnxRoot); + MY_CASE_STR(ContLnxReserved); + MY_CASE_STR(ContLnxRootRAID); + MY_CASE_STR(HaikuBFS); + MY_CASE_STR(MidntBSDBoot); + MY_CASE_STR(MidntBSDData); + MY_CASE_STR(MidntBSDSwap); + MY_CASE_STR(MidntBSDUFS); + MY_CASE_STR(MidntBSDVium); + MY_CASE_STR(MidntBSDZFS); + MY_CASE_STR(MidntBSDUnknown); + MY_CASE_STR(OpenBSDData); + MY_CASE_STR(QNXPowerSafeFS); + MY_CASE_STR(Plan9); + MY_CASE_STR(VMWareVMKCore); + MY_CASE_STR(VMWareVMFS); + MY_CASE_STR(VMWareReserved); + MY_CASE_STR(VMWareUnknown); + MY_CASE_STR(AndroidX86Bootloader); + MY_CASE_STR(AndroidX86Bootloader2); + MY_CASE_STR(AndroidX86Boot); + MY_CASE_STR(AndroidX86Recovery); + MY_CASE_STR(AndroidX86Misc); + MY_CASE_STR(AndroidX86Metadata); + MY_CASE_STR(AndroidX86System); + MY_CASE_STR(AndroidX86Cache); + MY_CASE_STR(AndroidX86Data); + MY_CASE_STR(AndroidX86Persistent); + MY_CASE_STR(AndroidX86Vendor); + MY_CASE_STR(AndroidX86Config); + MY_CASE_STR(AndroidX86Factory); + MY_CASE_STR(AndroidX86FactoryAlt); + MY_CASE_STR(AndroidX86Fastboot); + MY_CASE_STR(AndroidX86OEM); + MY_CASE_STR(AndroidARMMeta); + MY_CASE_STR(AndroidARMExt); + MY_CASE_STR(ONIEBoot); + MY_CASE_STR(ONIEConfig); + MY_CASE_STR(PowerPCPrep); + MY_CASE_STR(XDGShrBootConfig); + MY_CASE_STR(CephBlock); + MY_CASE_STR(CephBlockDB); + MY_CASE_STR(CephBlockDBDmc); + MY_CASE_STR(CephBlockDBDmcLUKS); + MY_CASE_STR(CephBlockDmc); + MY_CASE_STR(CephBlockDmcLUKS); + MY_CASE_STR(CephBlockWALog); + MY_CASE_STR(CephBlockWALogDmc); + MY_CASE_STR(CephBlockWALogDmcLUKS); + MY_CASE_STR(CephDisk); + MY_CASE_STR(CephDiskDmc); + MY_CASE_STR(CephJournal); + MY_CASE_STR(CephJournalDmc); + MY_CASE_STR(CephJournalDmcLUKS); + MY_CASE_STR(CephLockbox); + MY_CASE_STR(CephMultipathBlock1); + MY_CASE_STR(CephMultipathBlock2); + MY_CASE_STR(CephMultipathBlockDB); + MY_CASE_STR(CephMultipathBLockWALog); + MY_CASE_STR(CephMultipathJournal); + MY_CASE_STR(CephMultipathOSD); + MY_CASE_STR(CephOSD); + MY_CASE_STR(CephOSDDmc); + MY_CASE_STR(CephOSDDmcLUKS); +#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK + case PartitionType_32BitHack: break; +#endif + /* no default! */ + } +#undef MY_CASE_STR + return pszUnknown; +} + + +/** + * List all available host drives with their partitions. + * + * @returns See produceList. + * @param pVirtualBox Reference to the IVirtualBox pointer. + * @param fOptLong Long listing or human readable. + */ +static HRESULT listHostDrives(const ComPtr<IVirtualBox> pVirtualBox, bool fOptLong) +{ + HRESULT hrc = S_OK; + ComPtr<IHost> pHost; + CHECK_ERROR2I_RET(pVirtualBox, COMGETTER(Host)(pHost.asOutParam()), hrcCheck); + com::SafeIfaceArray<IHostDrive> apHostDrives; + CHECK_ERROR2I_RET(pHost, COMGETTER(HostDrives)(ComSafeArrayAsOutParam(apHostDrives)), hrcCheck); + for (size_t i = 0; i < apHostDrives.size(); ++i) + { + ComPtr<IHostDrive> pHostDrive = apHostDrives[i]; + + /* The drivePath and model attributes are accessible even when the object + is in 'limited' mode. */ + com::Bstr bstrDrivePath; + CHECK_ERROR(pHostDrive,COMGETTER(DrivePath)(bstrDrivePath.asOutParam())); + if (SUCCEEDED(hrc)) + RTPrintf(List::tr("%sDrive: %ls\n"), i > 0 ? "\n" : "", bstrDrivePath.raw()); + else + RTPrintf(List::tr("%sDrive: %Rhrc\n"), i > 0 ? "\n" : "", hrc); + + com::Bstr bstrModel; + CHECK_ERROR(pHostDrive,COMGETTER(Model)(bstrModel.asOutParam())); + if (FAILED(hrc)) + RTPrintf(List::tr("Model: %Rhrc\n"), hrc); + else if (bstrModel.isNotEmpty()) + RTPrintf(List::tr("Model: \"%ls\"\n"), bstrModel.raw()); + else + RTPrintf(List::tr("Model: unknown/inaccessible\n")); + + /* The other attributes are not accessible in limited mode and will fail + with E_ACCESSDENIED. Typically means the user cannot read the drive. */ + com::Bstr bstrUuidDisk; + hrc = pHostDrive->COMGETTER(Uuid)(bstrUuidDisk.asOutParam()); + if (SUCCEEDED(hrc) && !com::Guid(bstrUuidDisk).isZero()) + RTPrintf("UUID: %ls\n", bstrUuidDisk.raw()); + else if (hrc == E_ACCESSDENIED) + { + RTPrintf(List::tr("Further disk and partitioning information is not available for drive \"%ls\". (E_ACCESSDENIED)\n"), + bstrDrivePath.raw()); + continue; + } + else if (FAILED(hrc)) + { + RTPrintf("UUID: %Rhrc\n", hrc); + com::GlueHandleComErrorNoCtx(pHostDrive, hrc); + } + + LONG64 cbSize = 0; + hrc = pHostDrive->COMGETTER(Size)(&cbSize); + if (SUCCEEDED(hrc) && fOptLong) + RTPrintf(List::tr("Size: %llu bytes (%Rhcb)\n", "", cbSize), cbSize, cbSize); + else if (SUCCEEDED(hrc)) + RTPrintf(List::tr("Size: %Rhcb\n"), cbSize); + else + { + RTPrintf(List::tr("Size: %Rhrc\n"), hrc); + com::GlueHandleComErrorNoCtx(pHostDrive, hrc); + } + + ULONG cbSectorSize = 0; + hrc = pHostDrive->COMGETTER(SectorSize)(&cbSectorSize); + if (SUCCEEDED(hrc)) + RTPrintf(List::tr("Sector Size: %u bytes\n", "", cbSectorSize), cbSectorSize); + else + { + RTPrintf(List::tr("Sector Size: %Rhrc\n"), hrc); + com::GlueHandleComErrorNoCtx(pHostDrive, hrc); + } + + PartitioningType_T partitioningType = (PartitioningType_T)9999; + hrc = pHostDrive->COMGETTER(PartitioningType)(&partitioningType); + if (SUCCEEDED(hrc)) + RTPrintf(List::tr("Scheme: %s\n"), partitioningType == PartitioningType_MBR ? "MBR" : "GPT"); + else + { + RTPrintf(List::tr("Scheme: %Rhrc\n"), hrc); + com::GlueHandleComErrorNoCtx(pHostDrive, hrc); + } + + com::SafeIfaceArray<IHostDrivePartition> apHostDrivesPartitions; + hrc = pHostDrive->COMGETTER(Partitions)(ComSafeArrayAsOutParam(apHostDrivesPartitions)); + if (FAILED(hrc)) + { + RTPrintf(List::tr("Partitions: %Rhrc\n"), hrc); + com::GlueHandleComErrorNoCtx(pHostDrive, hrc); + } + else if (apHostDrivesPartitions.size() == 0) + RTPrintf(List::tr("Partitions: None (or not able to grok them).\n")); + else if (partitioningType == PartitioningType_MBR) + { + if (fOptLong) + RTPrintf(List::tr("Partitions: First Last\n" + "## Type Byte Size Byte Offset Cyl/Head/Sec Cyl/Head/Sec Active\n")); + else + RTPrintf(List::tr("Partitions: First Last\n" + "## Type Size Start Cyl/Head/Sec Cyl/Head/Sec Active\n")); + for (size_t j = 0; j < apHostDrivesPartitions.size(); ++j) + { + ComPtr<IHostDrivePartition> pHostDrivePartition = apHostDrivesPartitions[j]; + + ULONG idx = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Number)(&idx)); + ULONG uType = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(TypeMBR)(&uType)); + ULONG uStartCylinder = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(StartCylinder)(&uStartCylinder)); + ULONG uStartHead = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(StartHead)(&uStartHead)); + ULONG uStartSector = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(StartSector)(&uStartSector)); + ULONG uEndCylinder = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(EndCylinder)(&uEndCylinder)); + ULONG uEndHead = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(EndHead)(&uEndHead)); + ULONG uEndSector = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(EndSector)(&uEndSector)); + cbSize = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Size)(&cbSize)); + LONG64 offStart = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Start)(&offStart)); + BOOL fActive = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Active)(&fActive)); + PartitionType_T enmType = PartitionType_Unknown; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Type)(&enmType)); + + /* Max size & offset here is around 16TiB with 4KiB sectors. */ + if (fOptLong) /* cb/off: max 16TiB; idx: max 64. */ + RTPrintf("%2u %02x %14llu %14llu %4u/%3u/%2u %4u/%3u/%2u %s %s\n", + idx, uType, cbSize, offStart, + uStartCylinder, uStartHead, uStartSector, uEndCylinder, uEndHead, uEndSector, + fActive ? List::tr("yes") : List::tr("no"), PartitionTypeToString(enmType, "")); + else + RTPrintf("%2u %02x %8Rhcb %8Rhcb %4u/%3u/%2u %4u/%3u/%2u %s %s\n", + idx, uType, (uint64_t)cbSize, (uint64_t)offStart, + uStartCylinder, uStartHead, uStartSector, uEndCylinder, uEndHead, uEndSector, + fActive ? List::tr("yes") : List::tr("no"), PartitionTypeToString(enmType, "")); + } + } + else /* GPT */ + { + /* Determin the max partition type length to try reduce the table width: */ + size_t cchMaxType = 0; + for (size_t j = 0; j < apHostDrivesPartitions.size(); ++j) + { + ComPtr<IHostDrivePartition> pHostDrivePartition = apHostDrivesPartitions[j]; + PartitionType_T enmType = PartitionType_Unknown; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Type)(&enmType)); + size_t const cchTypeNm = strlen(PartitionTypeToString(enmType, "e530bf6d-2754-4e9d-b260-60a5d0b80457")); + cchMaxType = RT_MAX(cchTypeNm, cchMaxType); + } + cchMaxType = RT_MIN(cchMaxType, RTUUID_STR_LENGTH); + + if (fOptLong) + RTPrintf(List::tr( + "Partitions:\n" + "## %-*s Uuid Byte Size Byte Offset Active Name\n"), + (int)cchMaxType, List::tr("Type")); + else + RTPrintf(List::tr( + "Partitions:\n" + "## %-*s Uuid Size Start Active Name\n"), + (int)cchMaxType, List::tr("Type")); + + for (size_t j = 0; j < apHostDrivesPartitions.size(); ++j) + { + ComPtr<IHostDrivePartition> pHostDrivePartition = apHostDrivesPartitions[j]; + + ULONG idx = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Number)(&idx)); + com::Bstr bstrUuidType; + CHECK_ERROR(pHostDrivePartition, COMGETTER(TypeUuid)(bstrUuidType.asOutParam())); + com::Bstr bstrUuidPartition; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Uuid)(bstrUuidPartition.asOutParam())); + cbSize = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Size)(&cbSize)); + LONG64 offStart = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Start)(&offStart)); + BOOL fActive = 0; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Active)(&fActive)); + com::Bstr bstrName; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Name)(bstrName.asOutParam())); + + PartitionType_T enmType = PartitionType_Unknown; + CHECK_ERROR(pHostDrivePartition, COMGETTER(Type)(&enmType)); + + Utf8Str strTypeConv; + const char *pszTypeNm = PartitionTypeToString(enmType, NULL); + if (!pszTypeNm) + pszTypeNm = (strTypeConv = bstrUuidType).c_str(); + else if (strlen(pszTypeNm) >= RTUUID_STR_LENGTH /* includes '\0' */) + pszTypeNm -= RTUUID_STR_LENGTH - 1 - strlen(pszTypeNm); + + if (fOptLong) + RTPrintf("%2u %-*s %36ls %19llu %19llu %-3s %ls\n", idx, cchMaxType, pszTypeNm, + bstrUuidPartition.raw(), cbSize, offStart, fActive ? List::tr("on") : List::tr("off"), + bstrName.raw()); + else + RTPrintf("%2u %-*s %36ls %8Rhcb %8Rhcb %-3s %ls\n", idx, cchMaxType, pszTypeNm, + bstrUuidPartition.raw(), cbSize, offStart, fActive ? List::tr("on") : List::tr("off"), + bstrName.raw()); + } + } + } + return hrc; +} + + +/** + * The type of lists we can produce. + */ +enum ListType_T +{ + kListNotSpecified = 1000, + kListVMs, + kListRunningVMs, + kListOsTypes, + kListHostDvds, + kListHostFloppies, + kListInternalNetworks, + kListBridgedInterfaces, +#if defined(VBOX_WITH_NETFLT) + kListHostOnlyInterfaces, +#endif +#if defined(VBOX_WITH_VMNET) + kListHostOnlyNetworks, +#endif +#if defined(VBOX_WITH_CLOUD_NET) + kListCloudNetworks, +#endif + kListHostCpuIDs, + kListHostInfo, + kListHddBackends, + kListHdds, + kListDvds, + kListFloppies, + kListUsbHost, + kListUsbFilters, + kListSystemProperties, +#if defined(VBOX_WITH_UPDATE_AGENT) + kListUpdateAgents, +#endif + kListDhcpServers, + kListExtPacks, + kListGroups, + kListNatNetworks, + kListVideoInputDevices, + kListScreenShotFormats, + kListCloudProviders, + kListCloudProfiles, + kListCPUProfiles, + kListHostDrives +}; + + +/** + * Produces the specified listing. + * + * @returns S_OK or some COM error code that has been reported in full. + * @param enmList The list to produce. + * @param fOptLong Long (@c true) or short list format. + * @param pVirtualBox Reference to the IVirtualBox smart pointer. + */ +static HRESULT produceList(enum ListType_T enmCommand, bool fOptLong, bool fOptSorted, const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc = S_OK; + switch (enmCommand) + { + case kListNotSpecified: + AssertFailed(); + return E_FAIL; + + case kListVMs: + { + /* + * Get the list of all registered VMs + */ + com::SafeIfaceArray<IMachine> machines; + hrc = pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines)); + if (SUCCEEDED(hrc)) + { + /* + * Display it. + */ + if (!fOptSorted) + { + for (size_t i = 0; i < machines.size(); ++i) + if (machines[i]) + hrc = showVMInfo(pVirtualBox, machines[i], NULL, fOptLong ? VMINFO_STANDARD : VMINFO_COMPACT); + } + else + { + /* + * Sort the list by name before displaying it. + */ + std::vector<std::pair<com::Bstr, IMachine *> > sortedMachines; + for (size_t i = 0; i < machines.size(); ++i) + { + IMachine *pMachine = machines[i]; + if (pMachine) /* no idea why we need to do this... */ + { + Bstr bstrName; + pMachine->COMGETTER(Name)(bstrName.asOutParam()); + sortedMachines.push_back(std::pair<com::Bstr, IMachine *>(bstrName, pMachine)); + } + } + + std::sort(sortedMachines.begin(), sortedMachines.end()); + + for (size_t i = 0; i < sortedMachines.size(); ++i) + hrc = showVMInfo(pVirtualBox, sortedMachines[i].second, NULL, fOptLong ? VMINFO_STANDARD : VMINFO_COMPACT); + } + } + break; + } + + case kListRunningVMs: + { + /* + * Get the list of all _running_ VMs + */ + com::SafeIfaceArray<IMachine> machines; + hrc = pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines)); + com::SafeArray<MachineState_T> states; + if (SUCCEEDED(hrc)) + hrc = pVirtualBox->GetMachineStates(ComSafeArrayAsInParam(machines), ComSafeArrayAsOutParam(states)); + if (SUCCEEDED(hrc)) + { + /* + * Iterate through the collection + */ + for (size_t i = 0; i < machines.size(); ++i) + { + if (machines[i]) + { + MachineState_T machineState = states[i]; + switch (machineState) + { + case MachineState_Running: + case MachineState_Teleporting: + case MachineState_LiveSnapshotting: + case MachineState_Paused: + case MachineState_TeleportingPausedVM: + hrc = showVMInfo(pVirtualBox, machines[i], NULL, fOptLong ? VMINFO_STANDARD : VMINFO_COMPACT); + break; + default: break; /* Shut up MSC */ + } + } + } + } + break; + } + + case kListOsTypes: + { + com::SafeIfaceArray<IGuestOSType> coll; + hrc = pVirtualBox->COMGETTER(GuestOSTypes)(ComSafeArrayAsOutParam(coll)); + if (SUCCEEDED(hrc)) + { + /* + * Iterate through the collection. + */ + for (size_t i = 0; i < coll.size(); ++i) + { + ComPtr<IGuestOSType> guestOS; + guestOS = coll[i]; + Bstr guestId; + guestOS->COMGETTER(Id)(guestId.asOutParam()); + RTPrintf("ID: %ls\n", guestId.raw()); + Bstr guestDescription; + guestOS->COMGETTER(Description)(guestDescription.asOutParam()); + RTPrintf(List::tr("Description: %ls\n"), guestDescription.raw()); + Bstr familyId; + guestOS->COMGETTER(FamilyId)(familyId.asOutParam()); + RTPrintf(List::tr("Family ID: %ls\n"), familyId.raw()); + Bstr familyDescription; + guestOS->COMGETTER(FamilyDescription)(familyDescription.asOutParam()); + RTPrintf(List::tr("Family Desc: %ls\n"), familyDescription.raw()); + BOOL is64Bit; + guestOS->COMGETTER(Is64Bit)(&is64Bit); + RTPrintf(List::tr("64 bit: %RTbool\n"), is64Bit); + RTPrintf("\n"); + } + } + break; + } + + case kListHostDvds: + { + ComPtr<IHost> host; + CHECK_ERROR(pVirtualBox, COMGETTER(Host)(host.asOutParam())); + com::SafeIfaceArray<IMedium> coll; + CHECK_ERROR(host, COMGETTER(DVDDrives)(ComSafeArrayAsOutParam(coll))); + if (SUCCEEDED(hrc)) + { + for (size_t i = 0; i < coll.size(); ++i) + { + ComPtr<IMedium> dvdDrive = coll[i]; + Bstr uuid; + dvdDrive->COMGETTER(Id)(uuid.asOutParam()); + RTPrintf("UUID: %s\n", Utf8Str(uuid).c_str()); + Bstr location; + dvdDrive->COMGETTER(Location)(location.asOutParam()); + RTPrintf(List::tr("Name: %ls\n\n"), location.raw()); + } + } + break; + } + + case kListHostFloppies: + { + ComPtr<IHost> host; + CHECK_ERROR(pVirtualBox, COMGETTER(Host)(host.asOutParam())); + com::SafeIfaceArray<IMedium> coll; + CHECK_ERROR(host, COMGETTER(FloppyDrives)(ComSafeArrayAsOutParam(coll))); + if (SUCCEEDED(hrc)) + { + for (size_t i = 0; i < coll.size(); ++i) + { + ComPtr<IMedium> floppyDrive = coll[i]; + Bstr uuid; + floppyDrive->COMGETTER(Id)(uuid.asOutParam()); + RTPrintf("UUID: %s\n", Utf8Str(uuid).c_str()); + Bstr location; + floppyDrive->COMGETTER(Location)(location.asOutParam()); + RTPrintf(List::tr("Name: %ls\n\n"), location.raw()); + } + } + break; + } + + case kListInternalNetworks: + hrc = listInternalNetworks(pVirtualBox); + break; + + case kListBridgedInterfaces: +#if defined(VBOX_WITH_NETFLT) + case kListHostOnlyInterfaces: +#endif + hrc = listNetworkInterfaces(pVirtualBox, enmCommand == kListBridgedInterfaces); + break; + +#if defined(VBOX_WITH_VMNET) + case kListHostOnlyNetworks: + hrc = listHostOnlyNetworks(pVirtualBox); + break; +#endif + +#if defined(VBOX_WITH_CLOUD_NET) + case kListCloudNetworks: + hrc = listCloudNetworks(pVirtualBox); + break; +#endif + case kListHostInfo: + hrc = listHostInfo(pVirtualBox); + break; + + case kListHostCpuIDs: + { + ComPtr<IHost> Host; + CHECK_ERROR(pVirtualBox, COMGETTER(Host)(Host.asOutParam())); + + RTPrintf(List::tr("Host CPUIDs:\n\nLeaf no. EAX EBX ECX EDX\n")); + ULONG uCpuNo = 0; /* ASSUMES that CPU#0 is online. */ + static uint32_t const s_auCpuIdRanges[] = + { + UINT32_C(0x00000000), UINT32_C(0x0000007f), + UINT32_C(0x80000000), UINT32_C(0x8000007f), + UINT32_C(0xc0000000), UINT32_C(0xc000007f) + }; + for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2) + { + ULONG uEAX, uEBX, uECX, uEDX, cLeafs; + CHECK_ERROR(Host, GetProcessorCPUIDLeaf(uCpuNo, s_auCpuIdRanges[i], 0, &cLeafs, &uEBX, &uECX, &uEDX)); + if (cLeafs < s_auCpuIdRanges[i] || cLeafs > s_auCpuIdRanges[i+1]) + continue; + cLeafs++; + for (ULONG iLeaf = s_auCpuIdRanges[i]; iLeaf <= cLeafs; iLeaf++) + { + CHECK_ERROR(Host, GetProcessorCPUIDLeaf(uCpuNo, iLeaf, 0, &uEAX, &uEBX, &uECX, &uEDX)); + RTPrintf("%08x %08x %08x %08x %08x\n", iLeaf, uEAX, uEBX, uECX, uEDX); + } + } + break; + } + + case kListHddBackends: + hrc = listHddBackends(pVirtualBox); + break; + + case kListHdds: + { + com::SafeIfaceArray<IMedium> hdds; + CHECK_ERROR(pVirtualBox, COMGETTER(HardDisks)(ComSafeArrayAsOutParam(hdds))); + hrc = listMedia(pVirtualBox, hdds, List::tr("base"), fOptLong); + break; + } + + case kListDvds: + { + com::SafeIfaceArray<IMedium> dvds; + CHECK_ERROR(pVirtualBox, COMGETTER(DVDImages)(ComSafeArrayAsOutParam(dvds))); + hrc = listMedia(pVirtualBox, dvds, NULL, fOptLong); + break; + } + + case kListFloppies: + { + com::SafeIfaceArray<IMedium> floppies; + CHECK_ERROR(pVirtualBox, COMGETTER(FloppyImages)(ComSafeArrayAsOutParam(floppies))); + hrc = listMedia(pVirtualBox, floppies, NULL, fOptLong); + break; + } + + case kListUsbHost: + hrc = listUsbHost(pVirtualBox); + break; + + case kListUsbFilters: + hrc = listUsbFilters(pVirtualBox); + break; + + case kListSystemProperties: + hrc = listSystemProperties(pVirtualBox); + break; + +#ifdef VBOX_WITH_UPDATE_AGENT + case kListUpdateAgents: + hrc = listUpdateAgents(pVirtualBox); + break; +#endif + case kListDhcpServers: + hrc = listDhcpServers(pVirtualBox); + break; + + case kListExtPacks: + hrc = listExtensionPacks(pVirtualBox); + break; + + case kListGroups: + hrc = listGroups(pVirtualBox); + break; + + case kListNatNetworks: + hrc = listNATNetworks(fOptLong, fOptSorted, pVirtualBox); + break; + + case kListVideoInputDevices: + hrc = listVideoInputDevices(pVirtualBox); + break; + + case kListScreenShotFormats: + hrc = listScreenShotFormats(pVirtualBox); + break; + + case kListCloudProviders: + hrc = listCloudProviders(pVirtualBox); + break; + + case kListCloudProfiles: + hrc = listCloudProfiles(pVirtualBox, fOptLong); + break; + + case kListCPUProfiles: + hrc = listCPUProfiles(pVirtualBox, fOptLong, fOptSorted); + break; + + case kListHostDrives: + hrc = listHostDrives(pVirtualBox, fOptLong); + break; + /* No default here, want gcc warnings. */ + + } /* end switch */ + + return hrc; +} + +/** + * Handles the 'list' command. + * + * @returns Appropriate exit code. + * @param a Handler argument. + */ +RTEXITCODE handleList(HandlerArg *a) +{ + bool fOptLong = false; + bool fOptMultiple = false; + bool fOptSorted = false; + bool fFirst = true; + enum ListType_T enmOptCommand = kListNotSpecified; + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + + static const RTGETOPTDEF s_aListOptions[] = + { + { "--long", 'l', RTGETOPT_REQ_NOTHING }, + { "--multiple", 'm', RTGETOPT_REQ_NOTHING }, /* not offical yet */ + { "--sorted", 's', RTGETOPT_REQ_NOTHING }, + { "vms", kListVMs, RTGETOPT_REQ_NOTHING }, + { "runningvms", kListRunningVMs, RTGETOPT_REQ_NOTHING }, + { "ostypes", kListOsTypes, RTGETOPT_REQ_NOTHING }, + { "hostdvds", kListHostDvds, RTGETOPT_REQ_NOTHING }, + { "hostfloppies", kListHostFloppies, RTGETOPT_REQ_NOTHING }, + { "intnets", kListInternalNetworks, RTGETOPT_REQ_NOTHING }, + { "hostifs", kListBridgedInterfaces, RTGETOPT_REQ_NOTHING }, /* backward compatibility */ + { "bridgedifs", kListBridgedInterfaces, RTGETOPT_REQ_NOTHING }, +#if defined(VBOX_WITH_NETFLT) + { "hostonlyifs", kListHostOnlyInterfaces, RTGETOPT_REQ_NOTHING }, +#endif +#if defined(VBOX_WITH_VMNET) + { "hostonlynets", kListHostOnlyNetworks, RTGETOPT_REQ_NOTHING }, +#endif +#if defined(VBOX_WITH_CLOUD_NET) + { "cloudnets", kListCloudNetworks, RTGETOPT_REQ_NOTHING }, +#endif + { "natnetworks", kListNatNetworks, RTGETOPT_REQ_NOTHING }, + { "natnets", kListNatNetworks, RTGETOPT_REQ_NOTHING }, + { "hostinfo", kListHostInfo, RTGETOPT_REQ_NOTHING }, + { "hostcpuids", kListHostCpuIDs, RTGETOPT_REQ_NOTHING }, + { "hddbackends", kListHddBackends, RTGETOPT_REQ_NOTHING }, + { "hdds", kListHdds, RTGETOPT_REQ_NOTHING }, + { "dvds", kListDvds, RTGETOPT_REQ_NOTHING }, + { "floppies", kListFloppies, RTGETOPT_REQ_NOTHING }, + { "usbhost", kListUsbHost, RTGETOPT_REQ_NOTHING }, + { "usbfilters", kListUsbFilters, RTGETOPT_REQ_NOTHING }, + { "systemproperties", kListSystemProperties, RTGETOPT_REQ_NOTHING }, +#if defined(VBOX_WITH_UPDATE_AGENT) + { "updates", kListUpdateAgents, RTGETOPT_REQ_NOTHING }, +#endif + { "dhcpservers", kListDhcpServers, RTGETOPT_REQ_NOTHING }, + { "extpacks", kListExtPacks, RTGETOPT_REQ_NOTHING }, + { "groups", kListGroups, RTGETOPT_REQ_NOTHING }, + { "webcams", kListVideoInputDevices, RTGETOPT_REQ_NOTHING }, + { "screenshotformats", kListScreenShotFormats, RTGETOPT_REQ_NOTHING }, + { "cloudproviders", kListCloudProviders, RTGETOPT_REQ_NOTHING }, + { "cloudprofiles", kListCloudProfiles, RTGETOPT_REQ_NOTHING }, + { "cpu-profiles", kListCPUProfiles, RTGETOPT_REQ_NOTHING }, + { "hostdrives", kListHostDrives, RTGETOPT_REQ_NOTHING }, + }; + + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, s_aListOptions, RT_ELEMENTS(s_aListOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'l': /* --long */ + fOptLong = true; + break; + + case 's': + fOptSorted = true; + break; + + case 'm': + fOptMultiple = true; + if (enmOptCommand == kListNotSpecified) + break; + ch = enmOptCommand; + RT_FALL_THRU(); + + case kListVMs: + case kListRunningVMs: + case kListOsTypes: + case kListHostDvds: + case kListHostFloppies: + case kListInternalNetworks: + case kListBridgedInterfaces: +#if defined(VBOX_WITH_NETFLT) + case kListHostOnlyInterfaces: +#endif +#if defined(VBOX_WITH_VMNET) + case kListHostOnlyNetworks: +#endif +#if defined(VBOX_WITH_CLOUD_NET) + case kListCloudNetworks: +#endif + case kListHostInfo: + case kListHostCpuIDs: + case kListHddBackends: + case kListHdds: + case kListDvds: + case kListFloppies: + case kListUsbHost: + case kListUsbFilters: + case kListSystemProperties: +#if defined(VBOX_WITH_UPDATE_AGENT) + case kListUpdateAgents: +#endif + case kListDhcpServers: + case kListExtPacks: + case kListGroups: + case kListNatNetworks: + case kListVideoInputDevices: + case kListScreenShotFormats: + case kListCloudProviders: + case kListCloudProfiles: + case kListCPUProfiles: + case kListHostDrives: + enmOptCommand = (enum ListType_T)ch; + if (fOptMultiple) + { + if (fFirst) + fFirst = false; + else + RTPrintf("\n"); + RTPrintf("[%s]\n", ValueUnion.pDef->pszLong); + HRESULT hrc = produceList(enmOptCommand, fOptLong, fOptSorted, a->virtualBox); + if (FAILED(hrc)) + rcExit = RTEXITCODE_FAILURE; + } + break; + + case VINF_GETOPT_NOT_OPTION: + return errorSyntax(List::tr("Unknown subcommand \"%s\"."), ValueUnion.psz); + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + + /* + * If not in multiple list mode, we have to produce the list now. + */ + if (enmOptCommand == kListNotSpecified) + return errorSyntax(List::tr("Missing subcommand for \"list\" command.\n")); + if (!fOptMultiple) + { + HRESULT hrc = produceList(enmOptCommand, fOptLong, fOptSorted, a->virtualBox); + if (FAILED(hrc)) + rcExit = RTEXITCODE_FAILURE; + } + + return rcExit; +} + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageMetrics.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageMetrics.cpp new file mode 100644 index 00000000..57ca8b34 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageMetrics.cpp @@ -0,0 +1,671 @@ +/* $Id: VBoxManageMetrics.cpp $ */ +/** @file + * VBoxManage - The 'metrics' command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/asm.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/time.h> +#include <iprt/thread.h> +#include <VBox/log.h> + +#include <set> +#include <utility> + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Metrics); + +// funcs +/////////////////////////////////////////////////////////////////////////////// + + +static HRESULT parseFilterParameters(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComSafeArrayOut(BSTR, outMetrics), + ComSafeArrayOut(IUnknown *, outObjects)) +{ + HRESULT hrc = S_OK; + com::SafeArray<BSTR> retMetrics(1); + com::SafeIfaceArray <IUnknown> retObjects; + + Bstr metricNames, baseNames; + + /* Metric list */ + if (argc > 1) + metricNames = argv[1]; + else + { + metricNames = L"*"; + baseNames = L"*"; + } + metricNames.cloneTo(&retMetrics[0]); + + /* Object name */ + if (argc > 0 && strcmp(argv[0], "*")) + { + if (!strcmp(argv[0], "host")) + { + ComPtr<IHost> host; + CHECK_ERROR(aVirtualBox, COMGETTER(Host)(host.asOutParam())); + retObjects.reset(1); + host.queryInterfaceTo(&retObjects[0]); + } + else + { + ComPtr<IMachine> machine; + hrc = aVirtualBox->FindMachine(Bstr(argv[0]).raw(), + machine.asOutParam()); + if (SUCCEEDED(hrc)) + { + retObjects.reset(1); + machine.queryInterfaceTo(&retObjects[0]); + } + else + { + errorArgument(Metrics::tr("Invalid machine name: '%s'"), argv[0]); + return hrc; + } + } + + } + + retMetrics.detachTo(ComSafeArrayOutArg(outMetrics)); + retObjects.detachTo(ComSafeArrayOutArg(outObjects)); + + return hrc; +} + +static Bstr toBaseName(Utf8Str& aFullName) +{ + char *pszRaw = aFullName.mutableRaw(); + /* + * Currently there are two metrics which base name is the same as the + * sub-metric name: CPU/MHz and Net/<iface>/LinkSpeed. + */ + if (pszRaw && strcmp(pszRaw, "CPU/MHz") && !RTStrSimplePatternMatch("Net/*/LinkSpeed", pszRaw)) + { + char *pszSlash = strrchr(pszRaw, '/'); + if (pszSlash) + { + *pszSlash = 0; + aFullName.jolt(); + } + } + return Bstr(aFullName); +} + +static Bstr getObjectName(ComPtr<IUnknown> aObject) +{ + HRESULT hrc; + + ComPtr<IHost> host = aObject; + if (!host.isNull()) + return Bstr(Metrics::tr("host")); + + ComPtr<IMachine> machine = aObject; + if (!machine.isNull()) + { + Bstr name; + CHECK_ERROR(machine, COMGETTER(Name)(name.asOutParam())); + if (SUCCEEDED(hrc)) + return name; + } + return Bstr(Metrics::tr("unknown")); +} + +static void listAffectedMetrics(ComSafeArrayIn(IPerformanceMetric*, aMetrics)) +{ + HRESULT hrc; + com::SafeIfaceArray<IPerformanceMetric> metrics(ComSafeArrayInArg(aMetrics)); + if (metrics.size()) + { + ComPtr<IUnknown> object; + Bstr metricName; + RTPrintf(Metrics::tr("The following metrics were modified:\n\n" + "Object Metric\n" + "---------- --------------------\n")); + for (size_t i = 0; i < metrics.size(); i++) + { + CHECK_ERROR(metrics[i], COMGETTER(Object)(object.asOutParam())); + CHECK_ERROR(metrics[i], COMGETTER(MetricName)(metricName.asOutParam())); + RTPrintf("%-10ls %-20ls\n", + getObjectName(object).raw(), metricName.raw()); + } + RTPrintf("\n"); + } + else + { + RTMsgError(Metrics::tr("No metrics match the specified filter!")); + } +} + +/** + * list + */ +static RTEXITCODE handleMetricsList(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComPtr<IPerformanceCollector> performanceCollector) +{ + HRESULT hrc; + com::SafeArray<BSTR> metrics; + com::SafeIfaceArray<IUnknown> objects; + + setCurrentSubcommand(HELP_SCOPE_METRICS_LIST); + + hrc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox, + ComSafeArrayAsOutParam(metrics), + ComSafeArrayAsOutParam(objects)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + com::SafeIfaceArray<IPerformanceMetric> metricInfo; + + CHECK_ERROR(performanceCollector, + GetMetrics(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), + ComSafeArrayAsOutParam(metricInfo))); + + ComPtr<IUnknown> object; + Bstr metricName, unit, description; + ULONG period, count; + LONG minimum, maximum; + RTPrintf(Metrics::tr( +"Object Metric Unit Minimum Maximum Period Count Description\n" +"--------------- ---------------------------------------- ---- ---------- ---------- ---------- ---------- -----------\n")); + for (size_t i = 0; i < metricInfo.size(); i++) + { + CHECK_ERROR(metricInfo[i], COMGETTER(Object)(object.asOutParam())); + CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricName.asOutParam())); + CHECK_ERROR(metricInfo[i], COMGETTER(Period)(&period)); + CHECK_ERROR(metricInfo[i], COMGETTER(Count)(&count)); + CHECK_ERROR(metricInfo[i], COMGETTER(MinimumValue)(&minimum)); + CHECK_ERROR(metricInfo[i], COMGETTER(MaximumValue)(&maximum)); + CHECK_ERROR(metricInfo[i], COMGETTER(Unit)(unit.asOutParam())); + CHECK_ERROR(metricInfo[i], COMGETTER(Description)(description.asOutParam())); + RTPrintf("%-15ls %-40ls %-4ls %10d %10d %10u %10u %ls\n", + getObjectName(object).raw(), metricName.raw(), unit.raw(), + minimum, maximum, period, count, description.raw()); + } + + return RTEXITCODE_SUCCESS; +} + +/** + * Metrics setup + */ +static RTEXITCODE handleMetricsSetup(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComPtr<IPerformanceCollector> performanceCollector) +{ + HRESULT hrc; + com::SafeArray<BSTR> metrics; + com::SafeIfaceArray<IUnknown> objects; + uint32_t period = 1, samples = 1; + bool listMatches = false; + int i; + + setCurrentSubcommand(HELP_SCOPE_METRICS_SETUP); + + for (i = 1; i < argc; i++) + { + if ( !strcmp(argv[i], "--period") + || !strcmp(argv[i], "-period")) + { + if (argc <= i + 1) + return errorArgument(Metrics::tr("Missing argument to '%s'"), argv[i]); + if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period) + || !period) + return errorArgument(Metrics::tr("Invalid value for 'period' parameter: '%s'"), argv[i]); + } + else if ( !strcmp(argv[i], "--samples") + || !strcmp(argv[i], "-samples")) + { + if (argc <= i + 1) + return errorArgument(Metrics::tr("Missing argument to '%s'"), argv[i]); + if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples) + || !samples) + return errorArgument(Metrics::tr("Invalid value for 'samples' parameter: '%s'"), argv[i]); + } + else if ( !strcmp(argv[i], "--list") + || !strcmp(argv[i], "-list")) + listMatches = true; + else + break; /* The rest of params should define the filter */ + } + + hrc = parseFilterParameters(argc - i, &argv[i], aVirtualBox, + ComSafeArrayAsOutParam(metrics), + ComSafeArrayAsOutParam(objects)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + com::SafeIfaceArray<IPerformanceMetric> affectedMetrics; + CHECK_ERROR(performanceCollector, + SetupMetrics(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), period, samples, + ComSafeArrayAsOutParam(affectedMetrics))); + if (FAILED(hrc)) + return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */ + + if (listMatches) + listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics)); + + return RTEXITCODE_SUCCESS; +} + +/** + * metrics query + */ +static RTEXITCODE handleMetricsQuery(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComPtr<IPerformanceCollector> performanceCollector) +{ + HRESULT hrc; + com::SafeArray<BSTR> metrics; + com::SafeIfaceArray<IUnknown> objects; + + setCurrentSubcommand(HELP_SCOPE_METRICS_QUERY); + + hrc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox, + ComSafeArrayAsOutParam(metrics), + ComSafeArrayAsOutParam(objects)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + com::SafeArray<BSTR> retNames; + com::SafeIfaceArray<IUnknown> retObjects; + com::SafeArray<BSTR> retUnits; + com::SafeArray<ULONG> retScales; + com::SafeArray<ULONG> retSequenceNumbers; + com::SafeArray<ULONG> retIndices; + com::SafeArray<ULONG> retLengths; + com::SafeArray<LONG> retData; + CHECK_ERROR(performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), + ComSafeArrayAsOutParam(retNames), + ComSafeArrayAsOutParam(retObjects), + ComSafeArrayAsOutParam(retUnits), + ComSafeArrayAsOutParam(retScales), + ComSafeArrayAsOutParam(retSequenceNumbers), + ComSafeArrayAsOutParam(retIndices), + ComSafeArrayAsOutParam(retLengths), + ComSafeArrayAsOutParam(retData)) ); + + RTPrintf(Metrics::tr( + "Object Metric Values\n" + "--------------- ---------------------------------------- --------------------------------------------\n")); + for (unsigned i = 0; i < retNames.size(); i++) + { + Bstr metricUnit(retUnits[i]); + Bstr metricName(retNames[i]); + RTPrintf("%-15ls %-40ls ", getObjectName(retObjects[i]).raw(), metricName.raw()); + const char *separator = ""; + for (unsigned j = 0; j < retLengths[i]; j++) + { + if (retScales[i] == 1) + RTPrintf("%s%d %ls", separator, retData[retIndices[i] + j], metricUnit.raw()); + else + RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[i] + j] / retScales[i], + (retData[retIndices[i] + j] * 100 / retScales[i]) % 100, metricUnit.raw()); + separator = ", "; + } + RTPrintf("\n"); + } + + return RTEXITCODE_SUCCESS; +} + +static void getTimestamp(char *pts, size_t tsSize) +{ + *pts = 0; + AssertReturnVoid(tsSize >= 13); /* 3+3+3+3+1 */ + RTTIMESPEC TimeSpec; + RTTIME Time; + RTTimeExplode(&Time, RTTimeNow(&TimeSpec)); + pts += RTStrFormatNumber(pts, Time.u8Hour, 10, 2, 0, RTSTR_F_ZEROPAD); + *pts++ = ':'; + pts += RTStrFormatNumber(pts, Time.u8Minute, 10, 2, 0, RTSTR_F_ZEROPAD); + *pts++ = ':'; + pts += RTStrFormatNumber(pts, Time.u8Second, 10, 2, 0, RTSTR_F_ZEROPAD); + *pts++ = '.'; + pts += RTStrFormatNumber(pts, Time.u32Nanosecond / 1000000, 10, 3, 0, RTSTR_F_ZEROPAD); + *pts = 0; +} + +/** Used by the handleMetricsCollect loop. */ +static bool volatile g_fKeepGoing = true; + +#ifdef RT_OS_WINDOWS +/** + * Handler routine for catching Ctrl-C, Ctrl-Break and closing of + * the console. + * + * @returns true if handled, false if not handled. + * @param dwCtrlType The type of control signal. + * + * @remarks This is called on a new thread. + */ +static BOOL WINAPI ctrlHandler(DWORD dwCtrlType) RT_NOTHROW_DEF +{ + switch (dwCtrlType) + { + /* Ctrl-C or Ctrl-Break or Close */ + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + case CTRL_CLOSE_EVENT: + /* Let's shut down gracefully. */ + ASMAtomicWriteBool(&g_fKeepGoing, false); + return TRUE; + } + /* Don't care about the rest -- let it die a horrible death. */ + return FALSE; +} +#endif /* RT_OS_WINDOWS */ + +/** + * collect + */ +static RTEXITCODE handleMetricsCollect(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComPtr<IPerformanceCollector> performanceCollector) +{ + HRESULT hrc; + com::SafeArray<BSTR> metrics; + com::SafeIfaceArray<IUnknown> objects; + uint32_t period = 1, samples = 1; + bool isDetached = false, listMatches = false; + int i; + + setCurrentSubcommand(HELP_SCOPE_METRICS_COLLECT); + + for (i = 1; i < argc; i++) + { + if ( !strcmp(argv[i], "--period") + || !strcmp(argv[i], "-period")) + { + if (argc <= i + 1) + return errorArgument(Metrics::tr("Missing argument to '%s'"), argv[i]); + if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period) + || !period) + return errorArgument(Metrics::tr("Invalid value for 'period' parameter: '%s'"), argv[i]); + } + else if ( !strcmp(argv[i], "--samples") + || !strcmp(argv[i], "-samples")) + { + if (argc <= i + 1) + return errorArgument(Metrics::tr("Missing argument to '%s'"), argv[i]); + if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples) + || !samples) + return errorArgument(Metrics::tr("Invalid value for 'samples' parameter: '%s'"), argv[i]); + } + else if ( !strcmp(argv[i], "--list") + || !strcmp(argv[i], "-list")) + listMatches = true; + else if ( !strcmp(argv[i], "--detach") + || !strcmp(argv[i], "-detach")) + isDetached = true; + else + break; /* The rest of params should define the filter */ + } + + hrc = parseFilterParameters(argc - i, &argv[i], aVirtualBox, + ComSafeArrayAsOutParam(metrics), + ComSafeArrayAsOutParam(objects)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + com::SafeIfaceArray<IPerformanceMetric> metricInfo; + + CHECK_ERROR(performanceCollector, + GetMetrics(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), + ComSafeArrayAsOutParam(metricInfo))); + + std::set<std::pair<ComPtr<IUnknown>,Bstr> > baseMetrics; + ComPtr<IUnknown> objectFiltered; + Bstr metricNameFiltered; + for (i = 0; i < (int)metricInfo.size(); i++) + { + CHECK_ERROR(metricInfo[i], COMGETTER(Object)(objectFiltered.asOutParam())); + CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricNameFiltered.asOutParam())); + Utf8Str baseMetricName(metricNameFiltered); + baseMetrics.insert(std::make_pair(objectFiltered, toBaseName(baseMetricName))); + } + com::SafeArray<BSTR> baseMetricsFiltered(baseMetrics.size()); + com::SafeIfaceArray<IUnknown> objectsFiltered(baseMetrics.size()); + std::set<std::pair<ComPtr<IUnknown>,Bstr> >::iterator it; + i = 0; + for (it = baseMetrics.begin(); it != baseMetrics.end(); ++it) + { + it->first.queryInterfaceTo(&objectsFiltered[i]); + Bstr(it->second).detachTo(&baseMetricsFiltered[i++]); + } + com::SafeIfaceArray<IPerformanceMetric> affectedMetrics; + CHECK_ERROR(performanceCollector, + SetupMetrics(ComSafeArrayAsInParam(baseMetricsFiltered), + ComSafeArrayAsInParam(objectsFiltered), period, samples, + ComSafeArrayAsOutParam(affectedMetrics))); + if (FAILED(hrc)) + return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */ + + if (listMatches) + listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics)); + if (!affectedMetrics.size()) + return RTEXITCODE_FAILURE; + + if (isDetached) + { + RTMsgWarning(Metrics::tr("The background process holding collected metrics will shutdown\n" + "in few seconds, discarding all collected data and parameters.")); + return RTEXITCODE_SUCCESS; + } + +#ifdef RT_OS_WINDOWS + SetConsoleCtrlHandler(ctrlHandler, true); +#endif /* RT_OS_WINDOWS */ + + RTPrintf(Metrics::tr("Time stamp Object Metric Value\n")); + + while (g_fKeepGoing) + { + RTPrintf("------------ ---------- -------------------- --------------------\n"); + RTThreadSleep(period * 1000); // Sleep for 'period' seconds + char ts[15]; + + getTimestamp(ts, sizeof(ts)); + com::SafeArray<BSTR> retNames; + com::SafeIfaceArray<IUnknown> retObjects; + com::SafeArray<BSTR> retUnits; + com::SafeArray<ULONG> retScales; + com::SafeArray<ULONG> retSequenceNumbers; + com::SafeArray<ULONG> retIndices; + com::SafeArray<ULONG> retLengths; + com::SafeArray<LONG> retData; + CHECK_ERROR(performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), + ComSafeArrayAsOutParam(retNames), + ComSafeArrayAsOutParam(retObjects), + ComSafeArrayAsOutParam(retUnits), + ComSafeArrayAsOutParam(retScales), + ComSafeArrayAsOutParam(retSequenceNumbers), + ComSafeArrayAsOutParam(retIndices), + ComSafeArrayAsOutParam(retLengths), + ComSafeArrayAsOutParam(retData)) ); + for (unsigned j = 0; j < retNames.size(); j++) + { + Bstr metricUnit(retUnits[j]); + Bstr metricName(retNames[j]); + RTPrintf("%-12s %-10ls %-20ls ", ts, getObjectName(retObjects[j]).raw(), metricName.raw()); + const char *separator = ""; + for (unsigned k = 0; k < retLengths[j]; k++) + { + if (retScales[j] == 1) + RTPrintf("%s%d %ls", separator, retData[retIndices[j] + k], metricUnit.raw()); + else + RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[j] + k] / retScales[j], + (retData[retIndices[j] + k] * 100 / retScales[j]) % 100, metricUnit.raw()); + separator = ", "; + } + RTPrintf("\n"); + } + RTStrmFlush(g_pStdOut); + } + +#ifdef RT_OS_WINDOWS + SetConsoleCtrlHandler(ctrlHandler, false); +#endif /* RT_OS_WINDOWS */ + + return RTEXITCODE_SUCCESS; +} + +/** + * Enable metrics + */ +static RTEXITCODE handleMetricsEnable(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComPtr<IPerformanceCollector> performanceCollector) +{ + HRESULT hrc; + com::SafeArray<BSTR> metrics; + com::SafeIfaceArray<IUnknown> objects; + bool listMatches = false; + int i; + + setCurrentSubcommand(HELP_SCOPE_METRICS_ENABLE); + + for (i = 1; i < argc; i++) + { + if ( !strcmp(argv[i], "--list") + || !strcmp(argv[i], "-list")) + listMatches = true; + else + break; /* The rest of params should define the filter */ + } + + hrc = parseFilterParameters(argc - i, &argv[i], aVirtualBox, + ComSafeArrayAsOutParam(metrics), + ComSafeArrayAsOutParam(objects)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + com::SafeIfaceArray<IPerformanceMetric> affectedMetrics; + CHECK_ERROR(performanceCollector, + EnableMetrics(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), + ComSafeArrayAsOutParam(affectedMetrics))); + if (FAILED(hrc)) + return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */ + + if (listMatches) + listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics)); + + return RTEXITCODE_SUCCESS; +} + +/** + * Disable metrics + */ +static RTEXITCODE handleMetricsDisable(int argc, char *argv[], + ComPtr<IVirtualBox> aVirtualBox, + ComPtr<IPerformanceCollector> performanceCollector) +{ + HRESULT hrc; + com::SafeArray<BSTR> metrics; + com::SafeIfaceArray<IUnknown> objects; + bool listMatches = false; + int i; + + setCurrentSubcommand(HELP_SCOPE_METRICS_DISABLE); + + for (i = 1; i < argc; i++) + { + if ( !strcmp(argv[i], "--list") + || !strcmp(argv[i], "-list")) + listMatches = true; + else + break; /* The rest of params should define the filter */ + } + + hrc = parseFilterParameters(argc - i, &argv[i], aVirtualBox, + ComSafeArrayAsOutParam(metrics), + ComSafeArrayAsOutParam(objects)); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + com::SafeIfaceArray<IPerformanceMetric> affectedMetrics; + CHECK_ERROR(performanceCollector, + DisableMetrics(ComSafeArrayAsInParam(metrics), + ComSafeArrayAsInParam(objects), + ComSafeArrayAsOutParam(affectedMetrics))); + if (FAILED(hrc)) + return RTEXITCODE_SYNTAX; /** @todo figure out why we must return 2 here. */ + + if (listMatches) + listAffectedMetrics(ComSafeArrayAsInParam(affectedMetrics)); + + return RTEXITCODE_SUCCESS; +} + + +RTEXITCODE handleMetrics(HandlerArg *a) +{ + /* at least one option: subcommand name */ + if (a->argc < 1) + return errorSyntax(Metrics::tr("Subcommand missing")); + + ComPtr<IPerformanceCollector> performanceCollector; + CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(PerformanceCollector)(performanceCollector.asOutParam()), RTEXITCODE_FAILURE); + + RTEXITCODE rcExit; + if (!strcmp(a->argv[0], "list")) + rcExit = handleMetricsList(a->argc, a->argv, a->virtualBox, performanceCollector); + else if (!strcmp(a->argv[0], "setup")) + rcExit = handleMetricsSetup(a->argc, a->argv, a->virtualBox, performanceCollector); + else if (!strcmp(a->argv[0], "query")) + rcExit = handleMetricsQuery(a->argc, a->argv, a->virtualBox, performanceCollector); + else if (!strcmp(a->argv[0], "collect")) + rcExit = handleMetricsCollect(a->argc, a->argv, a->virtualBox, performanceCollector); + else if (!strcmp(a->argv[0], "enable")) + rcExit = handleMetricsEnable(a->argc, a->argv, a->virtualBox, performanceCollector); + else if (!strcmp(a->argv[0], "disable")) + rcExit = handleMetricsDisable(a->argc, a->argv, a->virtualBox, performanceCollector); + else + return errorSyntax(Metrics::tr("Invalid subcommand '%s'"), a->argv[0]); + + return rcExit; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp new file mode 100644 index 00000000..fca7a98c --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp @@ -0,0 +1,2920 @@ +/* $Id: VBoxManageMisc.cpp $ */ +/** @file + * VBoxManage - VirtualBox's command-line interface. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> +#include <VBox/com/NativeEventQueue.h> + +#include <iprt/asm.h> +#include <iprt/buildconfig.h> +#include <iprt/cidr.h> +#include <iprt/ctype.h> +#include <iprt/dir.h> +#include <iprt/env.h> +#include <iprt/file.h> +#include <iprt/sha.h> +#include <iprt/initterm.h> +#include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/cpp/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/stdarg.h> +#include <iprt/thread.h> +#include <iprt/uuid.h> +#include <iprt/getopt.h> +#include <iprt/ctype.h> +#include <VBox/version.h> +#include <VBox/log.h> + +#include "VBoxManage.h" + +#include <list> + +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Misc); + +static const RTGETOPTDEF g_aRegisterVMOptions[] = +{ + { "--password", 'p', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleRegisterVM(HandlerArg *a) +{ + HRESULT hrc; + const char *VMName = NULL; + + Bstr bstrVMName; + Bstr bstrPasswordFile; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aRegisterVMOptions, RT_ELEMENTS(g_aRegisterVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'p': // --password + bstrPasswordFile = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + if (bstrVMName.isEmpty()) + VMName = ValueUnion.psz; + else + return errorSyntax(Misc::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Misc::tr("Invalid option -%c"), c); + return errorSyntax(Misc::tr("Invalid option case %i"), c); + } + if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Misc::tr("unknown option: %s\n"), ValueUnion.psz); + if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + return errorSyntax(Misc::tr("error: %Rrs"), c); + } + } + + Utf8Str strPassword; + + if (bstrPasswordFile.isNotEmpty()) + { + if (bstrPasswordFile == "-") + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, Misc::tr("Enter password:")); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(a->argv[3], &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + return RTMsgErrorExitFailure(Misc::tr("Failed to read password from file")); + } + } + + ComPtr<IMachine> machine; + /** @todo Ugly hack to get both the API interpretation of relative paths + * and the client's interpretation of relative paths. Remove after the API + * has been redesigned. */ + hrc = a->virtualBox->OpenMachine(Bstr(a->argv[0]).raw(), + Bstr(strPassword).raw(), + machine.asOutParam()); + if (FAILED(hrc) && !RTPathStartsWithRoot(a->argv[0])) + { + char szVMFileAbs[RTPATH_MAX] = ""; + int vrc = RTPathAbs(a->argv[0], szVMFileAbs, sizeof(szVMFileAbs)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExitFailure(Misc::tr("Failed to convert \"%s\" to an absolute path: %Rrc"), + a->argv[0], vrc); + CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(szVMFileAbs).raw(), + Bstr(strPassword).raw(), + machine.asOutParam())); + } + else if (FAILED(hrc)) + com::GlueHandleComError(a->virtualBox, + "OpenMachine(Bstr(a->argv[0]).raw(), Bstr(strPassword).raw(), machine.asOutParam()))", + hrc, __FILE__, __LINE__); + if (SUCCEEDED(hrc)) + { + ASSERT(machine); + CHECK_ERROR(a->virtualBox, RegisterMachine(machine)); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aUnregisterVMOptions[] = +{ + { "--delete", 'd', RTGETOPT_REQ_NOTHING }, + { "-delete", 'd', RTGETOPT_REQ_NOTHING }, // deprecated + { "--delete-all", 'a', RTGETOPT_REQ_NOTHING }, + { "-delete-all", 'a', RTGETOPT_REQ_NOTHING }, // deprecated +}; + +RTEXITCODE handleUnregisterVM(HandlerArg *a) +{ + HRESULT hrc; + const char *VMName = NULL; + bool fDelete = false; + bool fDeleteAll = false; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aUnregisterVMOptions, RT_ELEMENTS(g_aUnregisterVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'd': // --delete + fDelete = true; + break; + + case 'a': // --delete-all + fDeleteAll = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!VMName) + VMName = ValueUnion.psz; + else + return errorSyntax(Misc::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Misc::tr("Invalid option -%c"), c); + return errorSyntax(Misc::tr("Invalid option case %i"), c); + } + if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Misc::tr("unknown option: %s\n"), ValueUnion.psz); + if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + return errorSyntax(Misc::tr("error: %Rrs"), c); + } + } + + /* check for required options */ + if (!VMName) + return errorSyntax(Misc::tr("VM name required")); + + ComPtr<IMachine> machine; + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(VMName).raw(), + machine.asOutParam()), + RTEXITCODE_FAILURE); + SafeIfaceArray<IMedium> aMedia; + CHECK_ERROR_RET(machine, Unregister(fDeleteAll ? CleanupMode_DetachAllReturnHardDisksAndVMRemovable + :CleanupMode_DetachAllReturnHardDisksOnly, + ComSafeArrayAsOutParam(aMedia)), + RTEXITCODE_FAILURE); + if (fDelete || fDeleteAll) + { + ComPtr<IProgress> pProgress; + CHECK_ERROR_RET(machine, DeleteConfig(ComSafeArrayAsInParam(aMedia), pProgress.asOutParam()), + RTEXITCODE_FAILURE); + + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR_RET(pProgress, (Misc::tr("Machine delete failed")), RTEXITCODE_FAILURE); + } + else + { + /* Note that the IMachine::Unregister method will return the medium + * reference in a sane order, which means that closing will normally + * succeed, unless there is still another machine which uses the + * medium. No harm done if we ignore the error. */ + for (size_t i = 0; i < aMedia.size(); i++) + { + IMedium *pMedium = aMedia[i]; + if (pMedium) + hrc = pMedium->Close(); + } + hrc = S_OK; /** @todo r=andy Why overwriting the result from closing the medium above? */ + } + return RTEXITCODE_SUCCESS; +} + +static const RTGETOPTDEF g_aCreateVMOptions[] = +{ + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "-name", 'n', RTGETOPT_REQ_STRING }, + { "--groups", 'g', RTGETOPT_REQ_STRING }, + { "--basefolder", 'p', RTGETOPT_REQ_STRING }, + { "-basefolder", 'p', RTGETOPT_REQ_STRING }, + { "--ostype", 'o', RTGETOPT_REQ_STRING }, + { "-ostype", 'o', RTGETOPT_REQ_STRING }, + { "--uuid", 'u', RTGETOPT_REQ_UUID }, + { "-uuid", 'u', RTGETOPT_REQ_UUID }, + { "--register", 'r', RTGETOPT_REQ_NOTHING }, + { "-register", 'r', RTGETOPT_REQ_NOTHING }, + { "--default", 'd', RTGETOPT_REQ_NOTHING }, + { "-default", 'd', RTGETOPT_REQ_NOTHING }, + { "--cipher", 'c', RTGETOPT_REQ_STRING }, + { "-cipher", 'c', RTGETOPT_REQ_STRING }, + { "--password-id", 'i', RTGETOPT_REQ_STRING }, + { "-password-id", 'i', RTGETOPT_REQ_STRING }, + { "--password", 'w', RTGETOPT_REQ_STRING }, + { "-password", 'w', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleCreateVM(HandlerArg *a) +{ + HRESULT hrc; + Bstr bstrBaseFolder; + Bstr bstrName; + Bstr bstrOsTypeId; + Bstr bstrUuid; + bool fRegister = false; + bool fDefault = false; + /* TBD. Now not used */ + Bstr bstrDefaultFlags; + com::SafeArray<BSTR> groups; + Bstr bstrCipher; + Bstr bstrPasswordId; + const char *pszPassword = NULL; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aCreateVMOptions, RT_ELEMENTS(g_aCreateVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'n': // --name + bstrName = ValueUnion.psz; + break; + + case 'g': // --groups + parseGroups(ValueUnion.psz, &groups); + break; + + case 'p': // --basefolder + bstrBaseFolder = ValueUnion.psz; + break; + + case 'o': // --ostype + bstrOsTypeId = ValueUnion.psz; + break; + + case 'u': // --uuid + bstrUuid = Guid(ValueUnion.Uuid).toUtf16().raw(); + break; + + case 'r': // --register + fRegister = true; + break; + + case 'd': // --default + fDefault = true; + break; + + case 'c': // --cipher + bstrCipher = ValueUnion.psz; + break; + + case 'i': // --password-id + bstrPasswordId = ValueUnion.psz; + break; + + case 'w': // --password + pszPassword = ValueUnion.psz; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* check for required options */ + if (bstrName.isEmpty()) + return errorSyntax(Misc::tr("Parameter --name is required")); + + do + { + Bstr createFlags; + if (!bstrUuid.isEmpty()) + createFlags = BstrFmt("UUID=%ls", bstrUuid.raw()); + Bstr bstrPrimaryGroup; + if (groups.size()) + bstrPrimaryGroup = groups[0]; + Bstr bstrSettingsFile; + CHECK_ERROR_BREAK(a->virtualBox, + ComposeMachineFilename(bstrName.raw(), + bstrPrimaryGroup.raw(), + createFlags.raw(), + bstrBaseFolder.raw(), + bstrSettingsFile.asOutParam())); + Utf8Str strPassword; + if (pszPassword) + { + if (!RTStrCmp(pszPassword, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPassword, &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read new password from file"); + return rcExit; + } + } + } + ComPtr<IMachine> machine; + CHECK_ERROR_BREAK(a->virtualBox, + CreateMachine(bstrSettingsFile.raw(), + bstrName.raw(), + ComSafeArrayAsInParam(groups), + bstrOsTypeId.raw(), + createFlags.raw(), + bstrCipher.raw(), + bstrPasswordId.raw(), + Bstr(strPassword).raw(), + machine.asOutParam())); + + CHECK_ERROR_BREAK(machine, SaveSettings()); + if (fDefault) + { + /* ApplyDefaults assumes the machine is already registered */ + CHECK_ERROR_BREAK(machine, ApplyDefaults(bstrDefaultFlags.raw())); + CHECK_ERROR_BREAK(machine, SaveSettings()); + } + if (fRegister) + { + CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine)); + } + + Bstr uuid; + CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam())); + Bstr settingsFile; + CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam())); + RTPrintf(Misc::tr("Virtual machine '%ls' is created%s.\n" + "UUID: %s\n" + "Settings file: '%ls'\n"), + bstrName.raw(), fRegister ? Misc::tr(" and registered") : "", + Utf8Str(uuid).c_str(), settingsFile.raw()); + } + while (0); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aMoveVMOptions[] = +{ + { "--type", 't', RTGETOPT_REQ_STRING }, + { "--folder", 'f', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleMoveVM(HandlerArg *a) +{ + HRESULT hrc; + const char *pszSrcName = NULL; + const char *pszType = NULL; + char szTargetFolder[RTPATH_MAX]; + + int c; + int vrc = VINF_SUCCESS; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aMoveVMOptions, RT_ELEMENTS(g_aMoveVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 't': // --type + pszType = ValueUnion.psz; + break; + + case 'f': // --target folder + if (ValueUnion.psz && ValueUnion.psz[0] != '\0') + { + vrc = RTPathAbs(ValueUnion.psz, szTargetFolder, sizeof(szTargetFolder)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("RTPathAbs(%s,,) failed with vrc=%Rrc"), + ValueUnion.psz, vrc); + } else { + szTargetFolder[0] = '\0'; + } + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszSrcName) + pszSrcName = ValueUnion.psz; + else + return errorSyntax(Misc::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + + if (!pszType) + pszType = "basic"; + + /* Check for required options */ + if (!pszSrcName) + return errorSyntax(Misc::tr("VM name required")); + + /* Get the machine object */ + ComPtr<IMachine> srcMachine; + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(pszSrcName).raw(), + srcMachine.asOutParam()), + RTEXITCODE_FAILURE); + + if (srcMachine) + { + /* Start the moving */ + ComPtr<IProgress> progress; + + /* we have to open a session for this task */ + CHECK_ERROR_RET(srcMachine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE); + ComPtr<IMachine> sessionMachine; + + CHECK_ERROR_RET(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(sessionMachine, + MoveTo(Bstr(szTargetFolder).raw(), + Bstr(pszType).raw(), + progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Misc::tr("Move VM failed")), RTEXITCODE_FAILURE); + + sessionMachine.setNull(); + CHECK_ERROR_RET(a->session, UnlockMachine(), RTEXITCODE_FAILURE); + + RTPrintf(Misc::tr("Machine has been successfully moved into %s\n"), + szTargetFolder[0] != '\0' ? szTargetFolder : Misc::tr("the same location")); + } + + return RTEXITCODE_SUCCESS; +} + +static const RTGETOPTDEF g_aCloneVMOptions[] = +{ + { "--snapshot", 's', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--groups", 'g', RTGETOPT_REQ_STRING }, + { "--mode", 'm', RTGETOPT_REQ_STRING }, + { "--options", 'o', RTGETOPT_REQ_STRING }, + { "--register", 'r', RTGETOPT_REQ_NOTHING }, + { "--basefolder", 'p', RTGETOPT_REQ_STRING }, + { "--uuid", 'u', RTGETOPT_REQ_UUID }, +}; + +static int parseCloneMode(const char *psz, CloneMode_T *pMode) +{ + if (!RTStrICmp(psz, "machine")) + *pMode = CloneMode_MachineState; + else if (!RTStrICmp(psz, "machineandchildren")) + *pMode = CloneMode_MachineAndChildStates; + else if (!RTStrICmp(psz, "all")) + *pMode = CloneMode_AllStates; + else + return VERR_PARSE_ERROR; + + return VINF_SUCCESS; +} + +static int parseCloneOptions(const char *psz, com::SafeArray<CloneOptions_T> *options) +{ + int vrc = VINF_SUCCESS; + while (psz && *psz && RT_SUCCESS(vrc)) + { + size_t len; + const char *pszComma = strchr(psz, ','); + if (pszComma) + len = pszComma - psz; + else + len = strlen(psz); + if (len > 0) + { + if (!RTStrNICmp(psz, "KeepAllMACs", len)) + options->push_back(CloneOptions_KeepAllMACs); + else if (!RTStrNICmp(psz, "KeepNATMACs", len)) + options->push_back(CloneOptions_KeepNATMACs); + else if (!RTStrNICmp(psz, "KeepDiskNames", len)) + options->push_back(CloneOptions_KeepDiskNames); + else if ( !RTStrNICmp(psz, "Link", len) + || !RTStrNICmp(psz, "Linked", len)) + options->push_back(CloneOptions_Link); + else if ( !RTStrNICmp(psz, "KeepHwUUIDs", len) + || !RTStrNICmp(psz, "KeepHwUUID", len)) + options->push_back(CloneOptions_KeepHwUUIDs); + else + vrc = VERR_PARSE_ERROR; + } + if (pszComma) + psz += len + 1; + else + psz += len; + } + + return vrc; +} + +RTEXITCODE handleCloneVM(HandlerArg *a) +{ + HRESULT hrc; + const char *pszSrcName = NULL; + const char *pszSnapshotName = NULL; + CloneMode_T mode = CloneMode_MachineState; + com::SafeArray<CloneOptions_T> options; + const char *pszTrgName = NULL; + const char *pszTrgBaseFolder = NULL; + bool fRegister = false; + Bstr bstrUuid; + com::SafeArray<BSTR> groups; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneVMOptions, RT_ELEMENTS(g_aCloneVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 's': // --snapshot + pszSnapshotName = ValueUnion.psz; + break; + + case 'n': // --name + pszTrgName = ValueUnion.psz; + break; + + case 'g': // --groups + parseGroups(ValueUnion.psz, &groups); + break; + + case 'p': // --basefolder + pszTrgBaseFolder = ValueUnion.psz; + break; + + case 'm': // --mode + if (RT_FAILURE(parseCloneMode(ValueUnion.psz, &mode))) + return errorArgument(Misc::tr("Invalid clone mode '%s'\n"), ValueUnion.psz); + break; + + case 'o': // --options + if (RT_FAILURE(parseCloneOptions(ValueUnion.psz, &options))) + return errorArgument(Misc::tr("Invalid clone options '%s'\n"), ValueUnion.psz); + break; + + case 'u': // --uuid + bstrUuid = Guid(ValueUnion.Uuid).toUtf16().raw(); + break; + + case 'r': // --register + fRegister = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (!pszSrcName) + pszSrcName = ValueUnion.psz; + else + return errorSyntax(Misc::tr("Invalid parameter '%s'"), ValueUnion.psz); + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* Check for required options */ + if (!pszSrcName) + return errorSyntax(Misc::tr("VM name required")); + + /* Get the machine object */ + ComPtr<IMachine> srcMachine; + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(pszSrcName).raw(), + srcMachine.asOutParam()), + RTEXITCODE_FAILURE); + + /* If a snapshot name/uuid was given, get the particular machine of this + * snapshot. */ + if (pszSnapshotName) + { + ComPtr<ISnapshot> srcSnapshot; + CHECK_ERROR_RET(srcMachine, FindSnapshot(Bstr(pszSnapshotName).raw(), + srcSnapshot.asOutParam()), + RTEXITCODE_FAILURE); + CHECK_ERROR_RET(srcSnapshot, COMGETTER(Machine)(srcMachine.asOutParam()), + RTEXITCODE_FAILURE); + } + + /* Default name necessary? */ + if (!pszTrgName) + pszTrgName = RTStrAPrintf2(Misc::tr("%s Clone"), pszSrcName); + + Bstr createFlags; + if (!bstrUuid.isEmpty()) + createFlags = BstrFmt("UUID=%ls", bstrUuid.raw()); + Bstr bstrPrimaryGroup; + if (groups.size()) + bstrPrimaryGroup = groups[0]; + Bstr bstrSettingsFile; + CHECK_ERROR_RET(a->virtualBox, + ComposeMachineFilename(Bstr(pszTrgName).raw(), + bstrPrimaryGroup.raw(), + createFlags.raw(), + Bstr(pszTrgBaseFolder).raw(), + bstrSettingsFile.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<IMachine> trgMachine; + CHECK_ERROR_RET(a->virtualBox, CreateMachine(bstrSettingsFile.raw(), + Bstr(pszTrgName).raw(), + ComSafeArrayAsInParam(groups), + NULL, + createFlags.raw(), + NULL, + NULL, + NULL, + trgMachine.asOutParam()), + RTEXITCODE_FAILURE); + + /* Start the cloning */ + ComPtr<IProgress> progress; + CHECK_ERROR_RET(srcMachine, CloneTo(trgMachine, + mode, + ComSafeArrayAsInParam(options), + progress.asOutParam()), + RTEXITCODE_FAILURE); + hrc = showProgress(progress); + CHECK_PROGRESS_ERROR_RET(progress, (Misc::tr("Clone VM failed")), RTEXITCODE_FAILURE); + + if (fRegister) + CHECK_ERROR_RET(a->virtualBox, RegisterMachine(trgMachine), RTEXITCODE_FAILURE); + + Bstr bstrNewName; + CHECK_ERROR_RET(trgMachine, COMGETTER(Name)(bstrNewName.asOutParam()), RTEXITCODE_FAILURE); + RTPrintf(Misc::tr("Machine has been successfully cloned as \"%ls\"\n"), bstrNewName.raw()); + + return RTEXITCODE_SUCCESS; +} + +RTEXITCODE handleStartVM(HandlerArg *a) +{ + HRESULT hrc = S_OK; + std::list<const char *> VMs; + Bstr sessionType; + com::SafeArray<IN_BSTR> aBstrEnv; + const char *pszPassword = NULL; + const char *pszPasswordId = NULL; + Utf8Str strPassword; + +#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) + /* make sure the VM process will by default start on the same display as VBoxManage */ + { + const char *pszDisplay = RTEnvGet("DISPLAY"); + if (pszDisplay) + aBstrEnv.push_back(BstrFmt("DISPLAY=%s", pszDisplay).raw()); + const char *pszXAuth = RTEnvGet("XAUTHORITY"); + if (pszXAuth) + aBstrEnv.push_back(BstrFmt("XAUTHORITY=%s", pszXAuth).raw()); + } +#endif + + static const RTGETOPTDEF s_aStartVMOptions[] = + { + { "--type", 't', RTGETOPT_REQ_STRING }, + { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated + { "--putenv", 'E', RTGETOPT_REQ_STRING }, + { "--password", 'p', RTGETOPT_REQ_STRING }, + { "--password-id", 'i', RTGETOPT_REQ_STRING } + }; + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, s_aStartVMOptions, RT_ELEMENTS(s_aStartVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 't': // --type + if (!RTStrICmp(ValueUnion.psz, "gui")) + { + sessionType = "gui"; + } +#ifdef VBOX_WITH_VBOXSDL + else if (!RTStrICmp(ValueUnion.psz, "sdl")) + { + sessionType = "sdl"; + } +#endif +#ifdef VBOX_WITH_HEADLESS + else if (!RTStrICmp(ValueUnion.psz, "capture")) + { + sessionType = "capture"; + } + else if (!RTStrICmp(ValueUnion.psz, "headless")) + { + sessionType = "headless"; + } +#endif + else + sessionType = ValueUnion.psz; + break; + + case 'E': // --putenv + if (!RTStrStr(ValueUnion.psz, "\n")) + aBstrEnv.push_back(Bstr(ValueUnion.psz).raw()); + else + return errorSyntax(Misc::tr("Parameter to option --putenv must not contain any newline character")); + break; + + case 'p': // --password + pszPassword = ValueUnion.psz; + break; + + case 'i': // --password-id + pszPasswordId = ValueUnion.psz; + break; + + case VINF_GETOPT_NOT_OPTION: + VMs.push_back(ValueUnion.psz); + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Misc::tr("Invalid option -%c"), c); + else + return errorSyntax(Misc::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Misc::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax("%s: %Rrs", ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Misc::tr("error: %Rrs"), c); + } + } + + /* check for required options */ + if (VMs.empty()) + return errorSyntax(Misc::tr("at least one VM name or uuid required")); + + if (pszPassword) + { + if (!RTStrCmp(pszPassword, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPassword, &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read new password from file"); + return rcExit; + } + } + } + + for (std::list<const char *>::const_iterator it = VMs.begin(); + it != VMs.end(); + ++it) + { + HRESULT hrc2 = hrc; + const char *pszVM = *it; + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(pszVM).raw(), + machine.asOutParam())); + if (machine) + { + if (pszPasswordId && strPassword.isNotEmpty()) + { + CHECK_ERROR(machine, AddEncryptionPassword(Bstr(pszPasswordId).raw(), Bstr(strPassword).raw())); + if (hrc == VBOX_E_PASSWORD_INCORRECT) + RTMsgError("Password incorrect!"); + } + if (SUCCEEDED(hrc)) + { + ComPtr<IProgress> progress; + CHECK_ERROR(machine, LaunchVMProcess(a->session, sessionType.raw(), + ComSafeArrayAsInParam(aBstrEnv), progress.asOutParam())); + if (SUCCEEDED(hrc) && !progress.isNull()) + { + RTPrintf("Waiting for VM \"%s\" to power on...\n", pszVM); + CHECK_ERROR(progress, WaitForCompletion(-1)); + if (SUCCEEDED(hrc)) + { + BOOL completed = true; + CHECK_ERROR(progress, COMGETTER(Completed)(&completed)); + if (SUCCEEDED(hrc)) + { + ASSERT(completed); + + LONG iRc; + CHECK_ERROR(progress, COMGETTER(ResultCode)(&iRc)); + if (SUCCEEDED(hrc)) + { + if (SUCCEEDED(iRc)) + RTPrintf("VM \"%s\" has been successfully started.\n", pszVM); + else + { + ProgressErrorInfo info(progress); + com::GluePrintErrorInfo(info); + } + hrc = iRc; + } + } + } + } + } + } + + /* it's important to always close sessions */ + a->session->UnlockMachine(); + + /* make sure that we remember the failed state */ + if (FAILED(hrc2)) + hrc = hrc2; + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +#ifdef VBOX_WITH_FULL_VM_ENCRYPTION +static const RTGETOPTDEF g_aSetVMEncryptionOptions[] = +{ + { "--new-password", 'n', RTGETOPT_REQ_STRING }, + { "--old-password", 'o', RTGETOPT_REQ_STRING }, + { "--cipher", 'c', RTGETOPT_REQ_STRING }, + { "--new-password-id", 'i', RTGETOPT_REQ_STRING }, + { "--force", 'f', RTGETOPT_REQ_NOTHING}, +}; + +RTEXITCODE handleSetVMEncryption(HandlerArg *a, const char *pszFilenameOrUuid) +{ + HRESULT hrc; + ComPtr<IMachine> machine; + const char *pszPasswordNew = NULL; + const char *pszPasswordOld = NULL; + const char *pszCipher = NULL; + const char *pszNewPasswordId = NULL; + BOOL fForce = FALSE; + Utf8Str strPasswordNew; + Utf8Str strPasswordOld; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aSetVMEncryptionOptions, RT_ELEMENTS(g_aSetVMEncryptionOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'n': // --new-password + pszPasswordNew = ValueUnion.psz; + break; + + case 'o': // --old-password + pszPasswordOld = ValueUnion.psz; + break; + + case 'c': // --cipher + pszCipher = ValueUnion.psz; + break; + + case 'i': // --new-password-id + pszNewPasswordId = ValueUnion.psz; + break; + + case 'f': // --force + fForce = TRUE; + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Misc::tr("Invalid option -%c"), c); + else + return errorSyntax(Misc::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Misc::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax(Misc::tr("%s: %Rrs"), ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Misc::tr("error: %Rrs"), c); + } + } + + if (!pszFilenameOrUuid) + return errorSyntax(Misc::tr("VM name or UUID required")); + + if (!pszPasswordNew && !pszPasswordOld) + return errorSyntax(Misc::tr("No password specified")); + + if ( (pszPasswordNew && !pszNewPasswordId) + || (!pszPasswordNew && pszNewPasswordId)) + return errorSyntax(Misc::tr("A new password must always have a valid identifier set at the same time")); + + if (pszPasswordOld) + { + if (!RTStrCmp(pszPasswordOld, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordOld, "Enter old password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPasswordOld, &strPasswordOld); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read old password from file"); + return rcExit; + } + } + } + if (pszPasswordNew) + { + if (!RTStrCmp(pszPasswordNew, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPasswordNew, "Enter new password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPasswordNew, &strPasswordNew); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read new password from file"); + return rcExit; + } + } + } + + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(pszFilenameOrUuid).raw(), + machine.asOutParam())); + if (machine) + { + ComPtr<IProgress> progress; + CHECK_ERROR(machine, ChangeEncryption(Bstr(strPasswordOld).raw(), Bstr(pszCipher).raw(), + Bstr(strPasswordNew).raw(), Bstr(pszNewPasswordId).raw(), + fForce, progress.asOutParam())); + if (SUCCEEDED(hrc)) + hrc = showProgress(progress); + if (FAILED(hrc)) + { + if (hrc == E_NOTIMPL) + RTMsgError("Encrypt VM operation is not implemented!"); + else if (hrc == VBOX_E_NOT_SUPPORTED) + RTMsgError("Encrypt VM operation for this cipher is not implemented yet!"); + else if (!progress.isNull()) + CHECK_PROGRESS_ERROR(progress, ("Failed to encrypt the VM")); + else + RTMsgError("Failed to encrypt the VM!"); + } + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleCheckVMPassword(HandlerArg *a, const char *pszFilenameOrUuid) +{ + HRESULT hrc; + ComPtr<IMachine> machine; + Utf8Str strPassword; + + if (a->argc != 1) + return errorSyntax(Misc::tr("Invalid number of arguments: %d"), a->argc); + + if (!RTStrCmp(a->argv[0], "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(a->argv[0], &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read password from file"); + return rcExit; + } + } + + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(pszFilenameOrUuid).raw(), + machine.asOutParam())); + if (machine) + { + CHECK_ERROR(machine, CheckEncryptionPassword(Bstr(strPassword).raw())); + if (SUCCEEDED(hrc)) + RTPrintf("The given password is correct\n"); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static const RTGETOPTDEF g_aAddVMOptions[] = +{ + { "--password", 'p', RTGETOPT_REQ_STRING }, + { "--password-id", 'i', RTGETOPT_REQ_STRING } +}; + +RTEXITCODE handleAddVMPassword(HandlerArg *a, const char *pszFilenameOrUuid) +{ + HRESULT hrc; + ComPtr<IMachine> machine; + const char *pszPassword = NULL; + const char *pszPasswordId = NULL; + Utf8Str strPassword; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + // start at 0 because main() has hacked both the argc and argv given to us + RTGetOptInit(&GetState, a->argc, a->argv, g_aAddVMOptions, RT_ELEMENTS(g_aAddVMOptions), + 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'p': // --password + pszPassword = ValueUnion.psz; + break; + + case 'i': // --password-id + pszPasswordId = ValueUnion.psz; + break; + + default: + if (c > 0) + { + if (RT_C_IS_PRINT(c)) + return errorSyntax(Misc::tr("Invalid option -%c"), c); + else + return errorSyntax(Misc::tr("Invalid option case %i"), c); + } + else if (c == VERR_GETOPT_UNKNOWN_OPTION) + return errorSyntax(Misc::tr("unknown option: %s\n"), ValueUnion.psz); + else if (ValueUnion.pDef) + return errorSyntax(Misc::tr("%s: %Rrs"), ValueUnion.pDef->pszLong, c); + else + return errorSyntax(Misc::tr("error: %Rrs"), c); + } + } + + if (!pszFilenameOrUuid) + return errorSyntax(Misc::tr("VM name or UUID required")); + + if (!pszPassword) + return errorSyntax(Misc::tr("No password specified")); + + if (!pszPasswordId) + return errorSyntax(Misc::tr("No password identifier specified")); + + if (!RTStrCmp(pszPassword, "-")) + { + /* Get password from console. */ + RTEXITCODE rcExit = readPasswordFromConsole(&strPassword, "Enter the password:"); + if (rcExit == RTEXITCODE_FAILURE) + return rcExit; + } + else + { + RTEXITCODE rcExit = readPasswordFile(pszPassword, &strPassword); + if (rcExit == RTEXITCODE_FAILURE) + { + RTMsgError("Failed to read new password from file"); + return rcExit; + } + } + + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(pszFilenameOrUuid).raw(), + machine.asOutParam())); + if (machine) + { + ComPtr<IProgress> progress; + CHECK_ERROR(machine, AddEncryptionPassword(Bstr(pszPasswordId).raw(), Bstr(strPassword).raw())); + if (hrc == VBOX_E_PASSWORD_INCORRECT) + RTMsgError("Password incorrect!"); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleRemoveVMPassword(HandlerArg *a, const char *pszFilenameOrUuid) +{ + HRESULT hrc; + ComPtr<IMachine> machine; + + if (a->argc != 1) + return errorSyntax(Misc::tr("Invalid number of arguments: %d"), a->argc); + + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(pszFilenameOrUuid).raw(), + machine.asOutParam())); + if (machine) + { + CHECK_ERROR(machine, RemoveEncryptionPassword(Bstr(a->argv[0]).raw())); + if (hrc == VBOX_E_INVALID_VM_STATE) + RTMsgError("The machine is in online or transient state\n"); + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleEncryptVM(HandlerArg *a) +{ + if (a->argc < 2) + return errorSyntax(Misc::tr("subcommand required")); + + HandlerArg handlerArg; + handlerArg.argc = a->argc - 2; + handlerArg.argv = &a->argv[2]; + handlerArg.virtualBox = a->virtualBox; + handlerArg.session = a->session; + if (!strcmp(a->argv[1], "setencryption")) + return handleSetVMEncryption(&handlerArg, a->argv[0]); + if (!strcmp(a->argv[1], "checkpassword")) + return handleCheckVMPassword(&handlerArg, a->argv[0]); + if (!strcmp(a->argv[1], "addpassword")) + return handleAddVMPassword(&handlerArg, a->argv[0]); + if (!strcmp(a->argv[1], "removepassword")) + return handleRemoveVMPassword(&handlerArg, a->argv[0]); + return errorSyntax(Misc::tr("unknown subcommand")); +} +#endif /* !VBOX_WITH_FULL_VM_ENCRYPTION */ + +RTEXITCODE handleDiscardState(HandlerArg *a) +{ + HRESULT hrc; + + if (a->argc != 1) + return errorSyntax(Misc::tr("Incorrect number of parameters")); + + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + do + { + /* we have to open a session for this task */ + CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write)); + do + { + ComPtr<IMachine> sessionMachine; + CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam())); + CHECK_ERROR_BREAK(sessionMachine, DiscardSavedState(true /* fDeleteFile */)); + } while (0); + CHECK_ERROR_BREAK(a->session, UnlockMachine()); + } while (0); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleAdoptState(HandlerArg *a) +{ + HRESULT hrc; + + if (a->argc != 2) + return errorSyntax(Misc::tr("Incorrect number of parameters")); + + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + char szStateFileAbs[RTPATH_MAX] = ""; + int vrc = RTPathAbs(a->argv[1], szStateFileAbs, sizeof(szStateFileAbs)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("Cannot convert filename \"%s\" to absolute path: %Rrc"), + a->argv[0], vrc); + + do + { + /* we have to open a session for this task */ + CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write)); + do + { + ComPtr<IMachine> sessionMachine; + CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam())); + CHECK_ERROR_BREAK(sessionMachine, AdoptSavedState(Bstr(szStateFileAbs).raw())); + } while (0); + CHECK_ERROR_BREAK(a->session, UnlockMachine()); + } while (0); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleGetExtraData(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + if (a->argc > 2 || a->argc < 1) + return errorSyntax(Misc::tr("Incorrect number of parameters")); + + /* global data? */ + if (!strcmp(a->argv[0], "global")) + { + /* enumeration? */ + if (a->argc < 2 || !strcmp(a->argv[1], "enumerate")) + { + SafeArray<BSTR> aKeys; + CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys))); + + for (size_t i = 0; + i < aKeys.size(); + ++i) + { + Bstr bstrKey(aKeys[i]); + Bstr bstrValue; + CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey.raw(), + bstrValue.asOutParam())); + + RTPrintf(Misc::tr("Key: %ls, Value: %ls\n"), bstrKey.raw(), bstrValue.raw()); + } + } + else + { + Bstr value; + CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]).raw(), + value.asOutParam())); + if (!value.isEmpty()) + RTPrintf(Misc::tr("Value: %ls\n"), value.raw()); + else + RTPrintf(Misc::tr("No value set!\n")); + } + } + else + { + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + /* enumeration? */ + if (a->argc < 2 || !strcmp(a->argv[1], "enumerate")) + { + SafeArray<BSTR> aKeys; + CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys))); + + for (size_t i = 0; + i < aKeys.size(); + ++i) + { + Bstr bstrKey(aKeys[i]); + Bstr bstrValue; + CHECK_ERROR(machine, GetExtraData(bstrKey.raw(), + bstrValue.asOutParam())); + + RTPrintf(Misc::tr("Key: %ls, Value: %ls\n"), bstrKey.raw(), bstrValue.raw()); + } + } + else + { + Bstr value; + CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]).raw(), + value.asOutParam())); + if (!value.isEmpty()) + RTPrintf(Misc::tr("Value: %ls\n"), value.raw()); + else + RTPrintf(Misc::tr("No value set!\n")); + } + } + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleSetExtraData(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + if (a->argc < 2) + return errorSyntax(Misc::tr("Not enough parameters")); + + /* global data? */ + if (!strcmp(a->argv[0], "global")) + { + /** @todo passing NULL is deprecated */ + if (a->argc < 3) + CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]).raw(), + NULL)); + else if (a->argc == 3) + CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]).raw(), + Bstr(a->argv[2]).raw())); + else + return errorSyntax(Misc::tr("Too many parameters")); + } + else + { + ComPtr<IMachine> machine; + CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam())); + if (machine) + { + /* open an existing session for the VM */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + /* get the session machine */ + ComPtr<IMachine> sessionMachine; + CHECK_ERROR_RET(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()), RTEXITCODE_FAILURE); + /** @todo passing NULL is deprecated */ + if (a->argc < 3) + CHECK_ERROR(sessionMachine, SetExtraData(Bstr(a->argv[1]).raw(), + NULL)); + else if (a->argc == 3) + CHECK_ERROR(sessionMachine, SetExtraData(Bstr(a->argv[1]).raw(), + Bstr(a->argv[2]).raw())); + else + return errorSyntax(Misc::tr("Too many parameters")); + } + } + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleSetProperty(HandlerArg *a) +{ + HRESULT hrc; + + /* there must be two arguments: property name and value */ + if (a->argc != 2) + return errorSyntax(Misc::tr("Incorrect number of parameters")); + + ComPtr<ISystemProperties> systemProperties; + a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); + + if (!strcmp(a->argv[0], "machinefolder")) + { + /* reset to default? */ + if (!strcmp(a->argv[1], "default")) + CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL)); + else + CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1]).raw())); + } + else if (!strcmp(a->argv[0], "hwvirtexclusive")) + { + bool fHwVirtExclusive; + + if (!strcmp(a->argv[1], "on")) + fHwVirtExclusive = true; + else if (!strcmp(a->argv[1], "off")) + fHwVirtExclusive = false; + else + return errorArgument(Misc::tr("Invalid hwvirtexclusive argument '%s'"), a->argv[1]); + CHECK_ERROR(systemProperties, COMSETTER(ExclusiveHwVirt)(fHwVirtExclusive)); + } + else if ( !strcmp(a->argv[0], "vrdeauthlibrary") + || !strcmp(a->argv[0], "vrdpauthlibrary")) + { + if (!strcmp(a->argv[0], "vrdpauthlibrary")) + RTStrmPrintf(g_pStdErr, Misc::tr("Warning: 'vrdpauthlibrary' is deprecated. Use 'vrdeauthlibrary'.\n")); + + /* reset to default? */ + if (!strcmp(a->argv[1], "default")) + CHECK_ERROR(systemProperties, COMSETTER(VRDEAuthLibrary)(NULL)); + else + CHECK_ERROR(systemProperties, COMSETTER(VRDEAuthLibrary)(Bstr(a->argv[1]).raw())); + } + else if (!strcmp(a->argv[0], "websrvauthlibrary")) + { + /* reset to default? */ + if (!strcmp(a->argv[1], "default")) + CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL)); + else + CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1]).raw())); + } + else if (!strcmp(a->argv[0], "vrdeextpack")) + { + /* disable? */ + if (!strcmp(a->argv[1], "null")) + CHECK_ERROR(systemProperties, COMSETTER(DefaultVRDEExtPack)(NULL)); + else + CHECK_ERROR(systemProperties, COMSETTER(DefaultVRDEExtPack)(Bstr(a->argv[1]).raw())); + } + else if (!strcmp(a->argv[0], "loghistorycount")) + { + uint32_t uVal; + int vrc; + vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal); + if (vrc != VINF_SUCCESS) + return errorArgument(Misc::tr("Error parsing Log history count '%s'"), a->argv[1]); + CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal)); + } + else if (!strcmp(a->argv[0], "autostartdbpath")) + { + /* disable? */ + if (!strcmp(a->argv[1], "null")) + CHECK_ERROR(systemProperties, COMSETTER(AutostartDatabasePath)(NULL)); + else + CHECK_ERROR(systemProperties, COMSETTER(AutostartDatabasePath)(Bstr(a->argv[1]).raw())); + } + else if (!strcmp(a->argv[0], "defaultfrontend")) + { + Bstr bstrDefaultFrontend(a->argv[1]); + if (!strcmp(a->argv[1], "default")) + bstrDefaultFrontend.setNull(); + CHECK_ERROR(systemProperties, COMSETTER(DefaultFrontend)(bstrDefaultFrontend.raw())); + } + else if (!strcmp(a->argv[0], "logginglevel")) + { + Bstr bstrLoggingLevel(a->argv[1]); + if (!strcmp(a->argv[1], "default")) + bstrLoggingLevel.setNull(); + CHECK_ERROR(systemProperties, COMSETTER(LoggingLevel)(bstrLoggingLevel.raw())); + } + else if (!strcmp(a->argv[0], "proxymode")) + { + ProxyMode_T enmProxyMode; + if (!RTStrICmpAscii(a->argv[1], "system")) + enmProxyMode = ProxyMode_System; + else if (!RTStrICmpAscii(a->argv[1], "noproxy")) + enmProxyMode = ProxyMode_NoProxy; + else if (!RTStrICmpAscii(a->argv[1], "manual")) + enmProxyMode = ProxyMode_Manual; + else + return errorArgument(Misc::tr("Unknown proxy mode: '%s'"), a->argv[1]); + CHECK_ERROR(systemProperties, COMSETTER(ProxyMode)(enmProxyMode)); + } + else if (!strcmp(a->argv[0], "proxyurl")) + { + Bstr bstrProxyUrl(a->argv[1]); + CHECK_ERROR(systemProperties, COMSETTER(ProxyURL)(bstrProxyUrl.raw())); + } +#ifdef VBOX_WITH_MAIN_NLS + else if (!strcmp(a->argv[0], "language")) + { + Bstr bstrLanguage(a->argv[1]); + CHECK_ERROR(systemProperties, COMSETTER(LanguageId)(bstrLanguage.raw())); + + /* Kudge alert! Make sure the language change notification is processed, + otherwise it may arrive as (XP)COM shuts down and cause + trouble in debug builds. */ +# ifdef DEBUG + uint64_t const tsStart = RTTimeNanoTS(); +# endif + unsigned cMsgs = 0; + int vrc; + while ( RT_SUCCESS(vrc = NativeEventQueue::getMainEventQueue()->processEventQueue(32 /*ms*/)) + || vrc == VERR_INTERRUPTED) + cMsgs++; +# ifdef DEBUG + RTPrintf("vrc=%Rrc cMsgs=%u nsElapsed=%'RU64\n", vrc, cMsgs, RTTimeNanoTS() - tsStart); +# endif + } +#endif + else + return errorSyntax(Misc::tr("Invalid parameter '%s'"), a->argv[0]); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * sharedfolder add + */ +static RTEXITCODE handleSharedFolderAdd(HandlerArg *a) +{ + /* + * Parse arguments (argv[0] == subcommand). + */ + static const RTGETOPTDEF s_aAddOptions[] = + { + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "-name", 'n', RTGETOPT_REQ_STRING }, // deprecated + { "--hostpath", 'p', RTGETOPT_REQ_STRING }, + { "-hostpath", 'p', RTGETOPT_REQ_STRING }, // deprecated + { "--readonly", 'r', RTGETOPT_REQ_NOTHING }, + { "-readonly", 'r', RTGETOPT_REQ_NOTHING }, // deprecated + { "--transient", 't', RTGETOPT_REQ_NOTHING }, + { "-transient", 't', RTGETOPT_REQ_NOTHING }, // deprecated + { "--automount", 'a', RTGETOPT_REQ_NOTHING }, + { "-automount", 'a', RTGETOPT_REQ_NOTHING }, // deprecated + { "--auto-mount-point", 'm', RTGETOPT_REQ_STRING }, + }; + const char *pszMachineName = NULL; + const char *pszName = NULL; + const char *pszHostPath = NULL; + bool fTransient = false; + bool fWritable = true; + bool fAutoMount = false; + const char *pszAutoMountPoint = ""; + + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, s_aAddOptions, RT_ELEMENTS(s_aAddOptions), 1 /*iFirst*/, 0 /*fFlags*/); + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'n': + pszName = ValueUnion.psz; + break; + case 'p': + pszHostPath = ValueUnion.psz; + break; + case 'r': + fWritable = false; + break; + case 't': + fTransient = true; + break; + case 'a': + fAutoMount = true; + break; + case 'm': + pszAutoMountPoint = ValueUnion.psz; + break; + case VINF_GETOPT_NOT_OPTION: + if (pszMachineName) + return errorArgument(Misc::tr("Machine name is given more than once: first '%s', then '%s'"), + pszMachineName, ValueUnion.psz); + pszMachineName = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszMachineName) + return errorSyntax(Misc::tr("No machine was specified")); + + if (!pszName) + return errorSyntax(Misc::tr("No shared folder name (--name) was given")); + if (strchr(pszName, ' ')) + return errorSyntax(Misc::tr("Invalid shared folder name '%s': contains space"), pszName); + if (strchr(pszName, '\t')) + return errorSyntax(Misc::tr("Invalid shared folder name '%s': contains tabs"), pszName); + if (strchr(pszName, '\n') || strchr(pszName, '\r')) + return errorSyntax(Misc::tr("Invalid shared folder name '%s': contains newline"), pszName); + + if (!pszHostPath) + return errorSyntax(Misc::tr("No host path (--hostpath) was given")); + char szAbsHostPath[RTPATH_MAX]; + int vrc = RTPathAbs(pszHostPath, szAbsHostPath, sizeof(szAbsHostPath)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("RTAbsPath failed on '%s': %Rrc"), pszHostPath, vrc); + + /* + * Done parsing, do some work. + */ + ComPtr<IMachine> ptrMachine; + CHECK_ERROR2I_RET(a->virtualBox, FindMachine(Bstr(pszMachineName).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + AssertReturn(ptrMachine.isNotNull(), RTEXITCODE_FAILURE); + + HRESULT hrc; + if (fTransient) + { + /* open an existing session for the VM */ + CHECK_ERROR2I_RET(ptrMachine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + + /* get the session machine */ + ComPtr<IMachine> ptrSessionMachine; + CHECK_ERROR2I_RET(a->session, COMGETTER(Machine)(ptrSessionMachine.asOutParam()), RTEXITCODE_FAILURE); + + /* get the session console */ + ComPtr<IConsole> ptrConsole; + CHECK_ERROR2I_RET(a->session, COMGETTER(Console)(ptrConsole.asOutParam()), RTEXITCODE_FAILURE); + if (ptrConsole.isNull()) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("Machine '%s' is not currently running."), pszMachineName); + + CHECK_ERROR2(hrc, ptrConsole, CreateSharedFolder(Bstr(pszName).raw(), Bstr(szAbsHostPath).raw(), + fWritable, fAutoMount, Bstr(pszAutoMountPoint).raw())); + a->session->UnlockMachine(); + } + else + { + /* open a session for the VM */ + CHECK_ERROR2I_RET(ptrMachine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + ComPtr<IMachine> ptrSessionMachine; + CHECK_ERROR2I_RET(a->session, COMGETTER(Machine)(ptrSessionMachine.asOutParam()), RTEXITCODE_FAILURE); + + CHECK_ERROR2(hrc, ptrSessionMachine, CreateSharedFolder(Bstr(pszName).raw(), Bstr(szAbsHostPath).raw(), + fWritable, fAutoMount, Bstr(pszAutoMountPoint).raw())); + if (SUCCEEDED(hrc)) + { + CHECK_ERROR2(hrc, ptrSessionMachine, SaveSettings()); + } + + a->session->UnlockMachine(); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * sharedfolder remove + */ +static RTEXITCODE handleSharedFolderRemove(HandlerArg *a) +{ + /* + * Parse arguments (argv[0] == subcommand). + */ + static const RTGETOPTDEF s_aRemoveOptions[] = + { + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "-name", 'n', RTGETOPT_REQ_STRING }, // deprecated + { "--transient", 't', RTGETOPT_REQ_NOTHING }, + { "-transient", 't', RTGETOPT_REQ_NOTHING }, // deprecated + }; + const char *pszMachineName = NULL; + const char *pszName = NULL; + bool fTransient = false; + + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, s_aRemoveOptions, RT_ELEMENTS(s_aRemoveOptions), 1 /*iFirst*/, 0 /*fFlags*/); + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'n': + pszName = ValueUnion.psz; + break; + case 't': + fTransient = true; + break; + case VINF_GETOPT_NOT_OPTION: + if (pszMachineName) + return errorArgument(Misc::tr("Machine name is given more than once: first '%s', then '%s'"), + pszMachineName, ValueUnion.psz); + pszMachineName = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszMachineName) + return errorSyntax(Misc::tr("No machine was specified")); + if (!pszName) + return errorSyntax(Misc::tr("No shared folder name (--name) was given")); + + /* + * Done parsing, do some real work. + */ + ComPtr<IMachine> ptrMachine; + CHECK_ERROR2I_RET(a->virtualBox, FindMachine(Bstr(pszMachineName).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + AssertReturn(ptrMachine.isNotNull(), RTEXITCODE_FAILURE); + + HRESULT hrc; + if (fTransient) + { + /* open an existing session for the VM */ + CHECK_ERROR2I_RET(ptrMachine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + /* get the session machine */ + ComPtr<IMachine> ptrSessionMachine; + CHECK_ERROR2I_RET(a->session, COMGETTER(Machine)(ptrSessionMachine.asOutParam()), RTEXITCODE_FAILURE); + /* get the session console */ + ComPtr<IConsole> ptrConsole; + CHECK_ERROR2I_RET(a->session, COMGETTER(Console)(ptrConsole.asOutParam()), RTEXITCODE_FAILURE); + if (ptrConsole.isNull()) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("Machine '%s' is not currently running.\n"), pszMachineName); + + CHECK_ERROR2(hrc, ptrConsole, RemoveSharedFolder(Bstr(pszName).raw())); + + a->session->UnlockMachine(); + } + else + { + /* open a session for the VM */ + CHECK_ERROR2I_RET(ptrMachine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + ComPtr<IMachine> ptrSessionMachine; + CHECK_ERROR2I_RET(a->session, COMGETTER(Machine)(ptrSessionMachine.asOutParam()), RTEXITCODE_FAILURE); + + CHECK_ERROR2(hrc, ptrSessionMachine, RemoveSharedFolder(Bstr(pszName).raw())); + + /* commit and close the session */ + if (SUCCEEDED(hrc)) + { + CHECK_ERROR2(hrc, ptrSessionMachine, SaveSettings()); + } + a->session->UnlockMachine(); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +RTEXITCODE handleSharedFolder(HandlerArg *a) +{ + if (a->argc < 1) + return errorSyntax(Misc::tr("Not enough parameters")); + + if (!strcmp(a->argv[0], "add")) + { + setCurrentSubcommand(HELP_SCOPE_SHAREDFOLDER_ADD); + return handleSharedFolderAdd(a); + } + + if (!strcmp(a->argv[0], "remove")) + { + setCurrentSubcommand(HELP_SCOPE_SHAREDFOLDER_REMOVE); + return handleSharedFolderRemove(a); + } + + return errorUnknownSubcommand(a->argv[0]); +} + +RTEXITCODE handleExtPack(HandlerArg *a) +{ + if (a->argc < 1) + return errorNoSubcommand(); + + ComObjPtr<IExtPackManager> ptrExtPackMgr; + CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(ExtensionPackManager)(ptrExtPackMgr.asOutParam()), RTEXITCODE_FAILURE); + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + int ch; + HRESULT hrc = S_OK; + + if (!strcmp(a->argv[0], "install")) + { + setCurrentSubcommand(HELP_SCOPE_EXTPACK_INSTALL); + const char *pszName = NULL; + bool fReplace = false; + + static const RTGETOPTDEF s_aInstallOptions[] = + { + { "--replace", 'r', RTGETOPT_REQ_NOTHING }, + { "--accept-license", 'a', RTGETOPT_REQ_STRING }, + }; + + RTCList<RTCString> lstLicenseHashes; + RTGetOptInit(&GetState, a->argc, a->argv, s_aInstallOptions, RT_ELEMENTS(s_aInstallOptions), 1, 0 /*fFlags*/); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'r': + fReplace = true; + break; + + case 'a': + lstLicenseHashes.append(ValueUnion.psz); + lstLicenseHashes[lstLicenseHashes.size() - 1].toLower(); + break; + + case VINF_GETOPT_NOT_OPTION: + if (pszName) + return errorSyntax(Misc::tr("Too many extension pack names given to \"extpack uninstall\"")); + pszName = ValueUnion.psz; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + if (!pszName) + return errorSyntax(Misc::tr("No extension pack name was given to \"extpack install\"")); + + char szPath[RTPATH_MAX]; + int vrc = RTPathAbs(pszName, szPath, sizeof(szPath)); + if (RT_FAILURE(vrc)) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("RTPathAbs(%s,,) failed with vrc=%Rrc"), pszName, vrc); + + Bstr bstrTarball(szPath); + Bstr bstrName; + ComPtr<IExtPackFile> ptrExtPackFile; + CHECK_ERROR2I_RET(ptrExtPackMgr, OpenExtPackFile(bstrTarball.raw(), ptrExtPackFile.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR2I_RET(ptrExtPackFile, COMGETTER(Name)(bstrName.asOutParam()), RTEXITCODE_FAILURE); + BOOL fShowLicense = true; + CHECK_ERROR2I_RET(ptrExtPackFile, COMGETTER(ShowLicense)(&fShowLicense), RTEXITCODE_FAILURE); + if (fShowLicense) + { + Bstr bstrLicense; + CHECK_ERROR2I_RET(ptrExtPackFile, + QueryLicense(Bstr("").raw() /* PreferredLocale */, + Bstr("").raw() /* PreferredLanguage */, + Bstr("txt").raw() /* Format */, + bstrLicense.asOutParam()), RTEXITCODE_FAILURE); + Utf8Str strLicense(bstrLicense); + uint8_t abHash[RTSHA256_HASH_SIZE]; + char szDigest[RTSHA256_DIGEST_LEN + 1]; + RTSha256(strLicense.c_str(), strLicense.length(), abHash); + vrc = RTSha256ToString(abHash, szDigest, sizeof(szDigest)); + AssertRCStmt(vrc, szDigest[0] = '\0'); + if (lstLicenseHashes.contains(szDigest)) + RTPrintf(Misc::tr("License accepted.\n")); + else + { + RTPrintf("%s\n", strLicense.c_str()); + RTPrintf(Misc::tr("Do you agree to these license terms and conditions (y/n)? ")); + ch = RTStrmGetCh(g_pStdIn); + RTPrintf("\n"); + if (ch != 'y' && ch != 'Y') + { + RTPrintf(Misc::tr("Installation of \"%ls\" aborted.\n"), bstrName.raw()); + return RTEXITCODE_FAILURE; + } + if (szDigest[0]) + RTPrintf(Misc::tr("License accepted. For batch installation add\n" + "--accept-license=%s\n" + "to the VBoxManage command line.\n\n"), szDigest); + } + } + ComPtr<IProgress> ptrProgress; + CHECK_ERROR2I_RET(ptrExtPackFile, Install(fReplace, NULL, ptrProgress.asOutParam()), RTEXITCODE_FAILURE); + hrc = showProgress(ptrProgress); + CHECK_PROGRESS_ERROR_RET(ptrProgress, (Misc::tr("Failed to install \"%s\""), szPath), RTEXITCODE_FAILURE); + + RTPrintf(Misc::tr("Successfully installed \"%ls\".\n"), bstrName.raw()); + } + else if (!strcmp(a->argv[0], "uninstall")) + { + setCurrentSubcommand(HELP_SCOPE_EXTPACK_UNINSTALL); + const char *pszName = NULL; + bool fForced = false; + + static const RTGETOPTDEF s_aUninstallOptions[] = + { + { "--force", 'f', RTGETOPT_REQ_NOTHING }, + }; + + RTGetOptInit(&GetState, a->argc, a->argv, s_aUninstallOptions, RT_ELEMENTS(s_aUninstallOptions), 1, 0); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'f': + fForced = true; + break; + + case VINF_GETOPT_NOT_OPTION: + if (pszName) + return errorSyntax(Misc::tr("Too many extension pack names given to \"extpack uninstall\"")); + pszName = ValueUnion.psz; + break; + + default: + return errorGetOpt(ch, &ValueUnion); + } + } + if (!pszName) + return errorSyntax(Misc::tr("No extension pack name was given to \"extpack uninstall\"")); + + Bstr bstrName(pszName); + ComPtr<IProgress> ptrProgress; + CHECK_ERROR2I_RET(ptrExtPackMgr, Uninstall(bstrName.raw(), fForced, NULL, ptrProgress.asOutParam()), RTEXITCODE_FAILURE); + hrc = showProgress(ptrProgress); + CHECK_PROGRESS_ERROR_RET(ptrProgress, (Misc::tr("Failed to uninstall \"%s\""), pszName), RTEXITCODE_FAILURE); + + RTPrintf(Misc::tr("Successfully uninstalled \"%s\".\n"), pszName); + } + else if (!strcmp(a->argv[0], "cleanup")) + { + setCurrentSubcommand(HELP_SCOPE_EXTPACK_CLEANUP); + if (a->argc > 1) + return errorTooManyParameters(&a->argv[1]); + CHECK_ERROR2I_RET(ptrExtPackMgr, Cleanup(), RTEXITCODE_FAILURE); + RTPrintf(Misc::tr("Successfully performed extension pack cleanup\n")); + } + else + return errorUnknownSubcommand(a->argv[0]); + + return RTEXITCODE_SUCCESS; +} + +RTEXITCODE handleUnattendedDetect(HandlerArg *a) +{ + HRESULT hrc; + + /* + * Options. We work directly on an IUnattended instace while parsing + * the options. This saves a lot of extra clutter. + */ + bool fMachineReadable = false; + char szIsoPath[RTPATH_MAX]; + szIsoPath[0] = '\0'; + + /* + * Parse options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--iso", 'i', RTGETOPT_REQ_STRING }, + { "--machine-readable", 'M', RTGETOPT_REQ_NOTHING }, + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'i': // --iso + vrc = RTPathAbs(ValueUnion.psz, szIsoPath, sizeof(szIsoPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + break; + + case 'M': // --machine-readable. + fMachineReadable = true; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* + * Check for required stuff. + */ + if (szIsoPath[0] == '\0') + return errorSyntax(Misc::tr("No ISO specified")); + + /* + * Do the job. + */ + ComPtr<IUnattended> ptrUnattended; + CHECK_ERROR2_RET(hrc, a->virtualBox, CreateUnattendedInstaller(ptrUnattended.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(IsoPath)(Bstr(szIsoPath).raw()), RTEXITCODE_FAILURE); + CHECK_ERROR2(hrc, ptrUnattended, DetectIsoOS()); + RTEXITCODE rcExit = SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; + + /* + * Retrieve the results. + */ + Bstr bstrDetectedOSTypeId; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedOSTypeId)(bstrDetectedOSTypeId.asOutParam()), RTEXITCODE_FAILURE); + Bstr bstrDetectedVersion; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedOSVersion)(bstrDetectedVersion.asOutParam()), RTEXITCODE_FAILURE); + Bstr bstrDetectedFlavor; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedOSFlavor)(bstrDetectedFlavor.asOutParam()), RTEXITCODE_FAILURE); + Bstr bstrDetectedLanguages; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedOSLanguages)(bstrDetectedLanguages.asOutParam()), RTEXITCODE_FAILURE); + Bstr bstrDetectedHints; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedOSHints)(bstrDetectedHints.asOutParam()), RTEXITCODE_FAILURE); + SafeArray<BSTR> aImageNames; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedImageNames)(ComSafeArrayAsOutParam(aImageNames)), RTEXITCODE_FAILURE); + SafeArray<ULONG> aImageIndices; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(DetectedImageIndices)(ComSafeArrayAsOutParam(aImageIndices)), RTEXITCODE_FAILURE); + Assert(aImageNames.size() == aImageIndices.size()); + BOOL fInstallSupported = FALSE; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMGETTER(IsUnattendedInstallSupported)(&fInstallSupported), RTEXITCODE_FAILURE); + + if (fMachineReadable) + { + outputMachineReadableString("OSTypeId", &bstrDetectedOSTypeId); + outputMachineReadableString("OSVersion", &bstrDetectedVersion); + outputMachineReadableString("OSFlavor", &bstrDetectedFlavor); + outputMachineReadableString("OSLanguages", &bstrDetectedLanguages); + outputMachineReadableString("OSHints", &bstrDetectedHints); + for (size_t i = 0; i < aImageNames.size(); i++) + { + Bstr const bstrName = aImageNames[i]; + outputMachineReadableStringWithFmtName(&bstrName, false, "ImageIndex%u", aImageIndices[i]); + } + outputMachineReadableBool("IsInstallSupported", &fInstallSupported); + } + else + { + RTMsgInfo(Misc::tr("Detected '%s' to be:\n"), szIsoPath); + RTPrintf(Misc::tr(" OS TypeId = %ls\n" + " OS Version = %ls\n" + " OS Flavor = %ls\n" + " OS Languages = %ls\n" + " OS Hints = %ls\n"), + bstrDetectedOSTypeId.raw(), + bstrDetectedVersion.raw(), + bstrDetectedFlavor.raw(), + bstrDetectedLanguages.raw(), + bstrDetectedHints.raw()); + for (size_t i = 0; i < aImageNames.size(); i++) + RTPrintf(" Image #%-3u = %ls\n", aImageIndices[i], aImageNames[i]); + if (fInstallSupported) + RTPrintf(Misc::tr(" Unattended installation supported = yes\n")); + else + RTPrintf(Misc::tr(" Unattended installation supported = no\n")); + } + + return rcExit; +} + +RTEXITCODE handleUnattendedInstall(HandlerArg *a) +{ + HRESULT hrc; + char szAbsPath[RTPATH_MAX]; + + /* + * Options. We work directly on an IUnattended instance while parsing + * the options. This saves a lot of extra clutter. + */ + ComPtr<IUnattended> ptrUnattended; + CHECK_ERROR2_RET(hrc, a->virtualBox, CreateUnattendedInstaller(ptrUnattended.asOutParam()), RTEXITCODE_FAILURE); + RTCList<RTCString> arrPackageSelectionAdjustments; + ComPtr<IMachine> ptrMachine; + bool fDryRun = false; + const char *pszSessionType = "none"; + + /* + * Parse options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--iso", 'i', RTGETOPT_REQ_STRING }, + { "--user", 'u', RTGETOPT_REQ_STRING }, + { "--password", 'p', RTGETOPT_REQ_STRING }, + { "--password-file", 'X', RTGETOPT_REQ_STRING }, + { "--full-user-name", 'U', RTGETOPT_REQ_STRING }, + { "--key", 'k', RTGETOPT_REQ_STRING }, + { "--install-additions", 'A', RTGETOPT_REQ_NOTHING }, + { "--no-install-additions", 'N', RTGETOPT_REQ_NOTHING }, + { "--additions-iso", 'a', RTGETOPT_REQ_STRING }, + { "--install-txs", 't', RTGETOPT_REQ_NOTHING }, + { "--no-install-txs", 'T', RTGETOPT_REQ_NOTHING }, + { "--validation-kit-iso", 'K', RTGETOPT_REQ_STRING }, + { "--locale", 'l', RTGETOPT_REQ_STRING }, + { "--country", 'Y', RTGETOPT_REQ_STRING }, + { "--time-zone", 'z', RTGETOPT_REQ_STRING }, + { "--proxy", 'y', RTGETOPT_REQ_STRING }, + { "--hostname", 'H', RTGETOPT_REQ_STRING }, + { "--package-selection-adjustment", 's', RTGETOPT_REQ_STRING }, + { "--dry-run", 'D', RTGETOPT_REQ_NOTHING }, + // advance options: + { "--auxiliary-base-path", 'x', RTGETOPT_REQ_STRING }, + { "--image-index", 'm', RTGETOPT_REQ_UINT32 }, + { "--script-template", 'c', RTGETOPT_REQ_STRING }, + { "--post-install-template", 'C', RTGETOPT_REQ_STRING }, + { "--post-install-command", 'P', RTGETOPT_REQ_STRING }, + { "--extra-install-kernel-parameters", 'I', RTGETOPT_REQ_STRING }, + { "--language", 'L', RTGETOPT_REQ_STRING }, + // start vm related options: + { "--start-vm", 'S', RTGETOPT_REQ_STRING }, + /** @todo Add a --wait option too for waiting for the VM to shut down or + * something like that...? */ + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case VINF_GETOPT_NOT_OPTION: + if (ptrMachine.isNotNull()) + return errorSyntax(Misc::tr("VM name/UUID given more than once!")); + CHECK_ERROR2_RET(hrc, a->virtualBox, FindMachine(Bstr(ValueUnion.psz).raw(), ptrMachine.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Machine)(ptrMachine), RTEXITCODE_FAILURE); + break; + + case 'i': // --iso + vrc = RTPathAbs(ValueUnion.psz, szAbsPath, sizeof(szAbsPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(IsoPath)(Bstr(szAbsPath).raw()), RTEXITCODE_FAILURE); + break; + + case 'u': // --user + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(User)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'p': // --password + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Password)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'X': // --password-file + { + Utf8Str strPassword; + RTEXITCODE rcExit = readPasswordFile(ValueUnion.psz, &strPassword); + if (rcExit != RTEXITCODE_SUCCESS) + return rcExit; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Password)(Bstr(strPassword).raw()), RTEXITCODE_FAILURE); + break; + } + + case 'U': // --full-user-name + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(FullUserName)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'k': // --key + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(ProductKey)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'A': // --install-additions + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(InstallGuestAdditions)(TRUE), RTEXITCODE_FAILURE); + break; + case 'N': // --no-install-additions + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(InstallGuestAdditions)(FALSE), RTEXITCODE_FAILURE); + break; + case 'a': // --additions-iso + vrc = RTPathAbs(ValueUnion.psz, szAbsPath, sizeof(szAbsPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(AdditionsIsoPath)(Bstr(szAbsPath).raw()), RTEXITCODE_FAILURE); + break; + + case 't': // --install-txs + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(InstallTestExecService)(TRUE), RTEXITCODE_FAILURE); + break; + case 'T': // --no-install-txs + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(InstallTestExecService)(FALSE), RTEXITCODE_FAILURE); + break; + case 'K': // --valiation-kit-iso + vrc = RTPathAbs(ValueUnion.psz, szAbsPath, sizeof(szAbsPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(ValidationKitIsoPath)(Bstr(szAbsPath).raw()), RTEXITCODE_FAILURE); + break; + + case 'l': // --locale + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Locale)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'Y': // --country + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Country)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'z': // --time-zone; + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(TimeZone)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'y': // --proxy + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Proxy)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'H': // --hostname + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Hostname)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 's': // --package-selection-adjustment + arrPackageSelectionAdjustments.append(ValueUnion.psz); + break; + + case 'D': + fDryRun = true; + break; + + case 'x': // --auxiliary-base-path + vrc = RTPathAbs(ValueUnion.psz, szAbsPath, sizeof(szAbsPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(AuxiliaryBasePath)(Bstr(szAbsPath).raw()), RTEXITCODE_FAILURE); + break; + + case 'm': // --image-index + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(ImageIndex)(ValueUnion.u32), RTEXITCODE_FAILURE); + break; + + case 'c': // --script-template + vrc = RTPathAbs(ValueUnion.psz, szAbsPath, sizeof(szAbsPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(ScriptTemplatePath)(Bstr(szAbsPath).raw()), RTEXITCODE_FAILURE); + break; + + case 'C': // --post-install-script-template + vrc = RTPathAbs(ValueUnion.psz, szAbsPath, sizeof(szAbsPath)); + if (RT_FAILURE(vrc)) + return errorSyntax(Misc::tr("RTPathAbs failed on '%s': %Rrc"), ValueUnion.psz, vrc); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(PostInstallScriptTemplatePath)(Bstr(szAbsPath).raw()), RTEXITCODE_FAILURE); + break; + + case 'P': // --post-install-command. + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(PostInstallCommand)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'I': // --extra-install-kernel-parameters + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(ExtraInstallKernelParameters)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'L': // --language + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(Language)(Bstr(ValueUnion.psz).raw()), RTEXITCODE_FAILURE); + break; + + case 'S': // --start-vm + pszSessionType = ValueUnion.psz; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* + * Check for required stuff. + */ + if (ptrMachine.isNull()) + return errorSyntax(Misc::tr("Missing VM name/UUID")); + + /* + * Set accumulative attributes. + */ + if (arrPackageSelectionAdjustments.size() == 1) + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(PackageSelectionAdjustments)(Bstr(arrPackageSelectionAdjustments[0]).raw()), + RTEXITCODE_FAILURE); + else if (arrPackageSelectionAdjustments.size() > 1) + { + RTCString strAdjustments; + strAdjustments.join(arrPackageSelectionAdjustments, ";"); + CHECK_ERROR2_RET(hrc, ptrUnattended, COMSETTER(PackageSelectionAdjustments)(Bstr(strAdjustments).raw()), RTEXITCODE_FAILURE); + } + + /* + * Get details about the machine so we can display them below. + */ + Bstr bstrMachineName; + CHECK_ERROR2_RET(hrc, ptrMachine, COMGETTER(Name)(bstrMachineName.asOutParam()), RTEXITCODE_FAILURE); + Bstr bstrUuid; + CHECK_ERROR2_RET(hrc, ptrMachine, COMGETTER(Id)(bstrUuid.asOutParam()), RTEXITCODE_FAILURE); + BSTR bstrInstalledOS; + CHECK_ERROR2_RET(hrc, ptrMachine, COMGETTER(OSTypeId)(&bstrInstalledOS), RTEXITCODE_FAILURE); + Utf8Str strInstalledOS(bstrInstalledOS); + + /* + * Temporarily lock the machine to check whether it's running or not. + * We take this opportunity to disable the first run wizard. + */ + CHECK_ERROR2_RET(hrc, ptrMachine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + { + ComPtr<IConsole> ptrConsole; + CHECK_ERROR2(hrc, a->session, COMGETTER(Console)(ptrConsole.asOutParam())); + + if ( ptrConsole.isNull() + && SUCCEEDED(hrc) + && ( RTStrICmp(pszSessionType, "gui") == 0 + || RTStrICmp(pszSessionType, "none") == 0)) + { + ComPtr<IMachine> ptrSessonMachine; + CHECK_ERROR2(hrc, a->session, COMGETTER(Machine)(ptrSessonMachine.asOutParam())); + if (ptrSessonMachine.isNotNull()) + { + CHECK_ERROR2(hrc, ptrSessonMachine, SetExtraData(Bstr("GUI/FirstRun").raw(), Bstr("0").raw())); + } + } + + a->session->UnlockMachine(); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + if (ptrConsole.isNotNull()) + return RTMsgErrorExit(RTEXITCODE_FAILURE, Misc::tr("Machine '%ls' is currently running"), bstrMachineName.raw()); + } + + /* + * Do the work. + */ + RTMsgInfo(Misc::tr("%s unattended installation of %s in machine '%ls' (%ls).\n"), + RTStrICmp(pszSessionType, "none") == 0 ? Misc::tr("Preparing") : Misc::tr("Starting"), + strInstalledOS.c_str(), bstrMachineName.raw(), bstrUuid.raw()); + + CHECK_ERROR2_RET(hrc, ptrUnattended,Prepare(), RTEXITCODE_FAILURE); + if (!fDryRun) + { + CHECK_ERROR2_RET(hrc, ptrUnattended, ConstructMedia(), RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, ptrUnattended, ReconfigureVM(), RTEXITCODE_FAILURE); + } + + /* + * Retrieve and display the parameters actually used. + */ + RTMsgInfo(Misc::tr("Using values:\n")); +#define SHOW_ATTR(a_Attr, a_szText, a_Type, a_szFmt) do { \ + a_Type Value; \ + HRESULT hrc2 = ptrUnattended->COMGETTER(a_Attr)(&Value); \ + if (SUCCEEDED(hrc2)) \ + RTPrintf(" %32s = " a_szFmt "\n", a_szText, Value); \ + else \ + RTPrintf(Misc::tr(" %32s = failed: %Rhrc\n"), a_szText, hrc2); \ + } while (0) +#define SHOW_STR_ATTR(a_Attr, a_szText) do { \ + Bstr bstrString; \ + HRESULT hrc2 = ptrUnattended->COMGETTER(a_Attr)(bstrString.asOutParam()); \ + if (SUCCEEDED(hrc2)) \ + RTPrintf(" %32s = %ls\n", a_szText, bstrString.raw()); \ + else \ + RTPrintf(Misc::tr(" %32s = failed: %Rhrc\n"), a_szText, hrc2); \ + } while (0) + + SHOW_STR_ATTR(IsoPath, "isoPath"); + SHOW_STR_ATTR(User, "user"); + SHOW_STR_ATTR(Password, "password"); + SHOW_STR_ATTR(FullUserName, "fullUserName"); + SHOW_STR_ATTR(ProductKey, "productKey"); + SHOW_STR_ATTR(AdditionsIsoPath, "additionsIsoPath"); + SHOW_ATTR( InstallGuestAdditions, "installGuestAdditions", BOOL, "%RTbool"); + SHOW_STR_ATTR(ValidationKitIsoPath, "validationKitIsoPath"); + SHOW_ATTR( InstallTestExecService, "installTestExecService", BOOL, "%RTbool"); + SHOW_STR_ATTR(Locale, "locale"); + SHOW_STR_ATTR(Country, "country"); + SHOW_STR_ATTR(TimeZone, "timeZone"); + SHOW_STR_ATTR(Proxy, "proxy"); + SHOW_STR_ATTR(Hostname, "hostname"); + SHOW_STR_ATTR(PackageSelectionAdjustments, "packageSelectionAdjustments"); + SHOW_STR_ATTR(AuxiliaryBasePath, "auxiliaryBasePath"); + SHOW_ATTR( ImageIndex, "imageIndex", ULONG, "%u"); + SHOW_STR_ATTR(ScriptTemplatePath, "scriptTemplatePath"); + SHOW_STR_ATTR(PostInstallScriptTemplatePath, "postInstallScriptTemplatePath"); + SHOW_STR_ATTR(PostInstallCommand, "postInstallCommand"); + SHOW_STR_ATTR(ExtraInstallKernelParameters, "extraInstallKernelParameters"); + SHOW_STR_ATTR(Language, "language"); + SHOW_STR_ATTR(DetectedOSTypeId, "detectedOSTypeId"); + SHOW_STR_ATTR(DetectedOSVersion, "detectedOSVersion"); + SHOW_STR_ATTR(DetectedOSFlavor, "detectedOSFlavor"); + SHOW_STR_ATTR(DetectedOSLanguages, "detectedOSLanguages"); + SHOW_STR_ATTR(DetectedOSHints, "detectedOSHints"); + { + ULONG idxImage = 0; + HRESULT hrc2 = ptrUnattended->COMGETTER(ImageIndex)(&idxImage); + if (FAILED(hrc2)) + idxImage = 0; + SafeArray<BSTR> aImageNames; + hrc2 = ptrUnattended->COMGETTER(DetectedImageNames)(ComSafeArrayAsOutParam(aImageNames)); + if (SUCCEEDED(hrc2)) + { + SafeArray<ULONG> aImageIndices; + hrc2 = ptrUnattended->COMGETTER(DetectedImageIndices)(ComSafeArrayAsOutParam(aImageIndices)); + if (SUCCEEDED(hrc2)) + { + Assert(aImageNames.size() == aImageIndices.size()); + for (size_t i = 0; i < aImageNames.size(); i++) + { + char szTmp[64]; + RTStrPrintf(szTmp, sizeof(szTmp), "detectedImage[%u]%s", i, idxImage != aImageIndices[i] ? "" : "*"); + RTPrintf(" %32s = #%u: %ls\n", szTmp, aImageIndices[i], aImageNames[i]); + } + } + else + RTPrintf(Misc::tr(" %32s = failed: %Rhrc\n"), "detectedImageIndices", hrc2); + } + else + RTPrintf(Misc::tr(" %32 = failed: %Rhrc\n"), "detectedImageNames", hrc2); + } + +#undef SHOW_STR_ATTR +#undef SHOW_ATTR + + /* We can drop the IUnatteded object now. */ + ptrUnattended.setNull(); + + /* + * Start the VM if requested. + */ + if ( fDryRun + || RTStrICmp(pszSessionType, "none") == 0) + { + if (!fDryRun) + RTMsgInfo(Misc::tr("VM '%ls' (%ls) is ready to be started (e.g. VBoxManage startvm).\n"), bstrMachineName.raw(), bstrUuid.raw()); + hrc = S_OK; + } + else + { + com::SafeArray<IN_BSTR> aBstrEnv; +#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) + /* make sure the VM process will start on the same display as VBoxManage */ + const char *pszDisplay = RTEnvGet("DISPLAY"); + if (pszDisplay) + aBstrEnv.push_back(BstrFmt("DISPLAY=%s", pszDisplay).raw()); + const char *pszXAuth = RTEnvGet("XAUTHORITY"); + if (pszXAuth) + aBstrEnv.push_back(BstrFmt("XAUTHORITY=%s", pszXAuth).raw()); +#endif + ComPtr<IProgress> ptrProgress; + CHECK_ERROR2(hrc, ptrMachine, LaunchVMProcess(a->session, Bstr(pszSessionType).raw(), ComSafeArrayAsInParam(aBstrEnv), ptrProgress.asOutParam())); + if (SUCCEEDED(hrc) && !ptrProgress.isNull()) + { + RTMsgInfo(Misc::tr("Waiting for VM '%ls' to power on...\n"), bstrMachineName.raw()); + CHECK_ERROR2(hrc, ptrProgress, WaitForCompletion(-1)); + if (SUCCEEDED(hrc)) + { + BOOL fCompleted = true; + CHECK_ERROR2(hrc, ptrProgress, COMGETTER(Completed)(&fCompleted)); + if (SUCCEEDED(hrc)) + { + ASSERT(fCompleted); + + LONG iRc; + CHECK_ERROR2(hrc, ptrProgress, COMGETTER(ResultCode)(&iRc)); + if (SUCCEEDED(hrc)) + { + if (SUCCEEDED(iRc)) + RTMsgInfo(Misc::tr("VM '%ls' (%ls) has been successfully started.\n"), + bstrMachineName.raw(), bstrUuid.raw()); + else + { + ProgressErrorInfo info(ptrProgress); + com::GluePrintErrorInfo(info); + } + hrc = iRc; + } + } + } + } + + /* + * Do we wait for the VM to power down? + */ + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +RTEXITCODE handleUnattended(HandlerArg *a) +{ + /* + * Sub-command switch. + */ + if (a->argc < 1) + return errorNoSubcommand(); + + if (!strcmp(a->argv[0], "detect")) + { + setCurrentSubcommand(HELP_SCOPE_UNATTENDED_DETECT); + return handleUnattendedDetect(a); + } + + if (!strcmp(a->argv[0], "install")) + { + setCurrentSubcommand(HELP_SCOPE_UNATTENDED_INSTALL); + return handleUnattendedInstall(a); + } + + /* Consider some kind of create-vm-and-install-guest-os command. */ + return errorUnknownSubcommand(a->argv[0]); +} + +/** + * Common Cloud profile options. + */ +typedef struct +{ + const char *pszProviderName; + const char *pszProfileName; +} CLOUDPROFILECOMMONOPT; +typedef CLOUDPROFILECOMMONOPT *PCLOUDPROFILECOMMONOPT; + +/** + * Sets the properties of cloud profile + * + * @returns 0 on success, 1 on failure + */ + +static RTEXITCODE setCloudProfileProperties(HandlerArg *a, int iFirst, PCLOUDPROFILECOMMONOPT pCommonOpts) +{ + + HRESULT hrc = S_OK; + + Bstr bstrProvider(pCommonOpts->pszProviderName); + Bstr bstrProfile(pCommonOpts->pszProfileName); + + /* + * Parse options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--clouduser", 'u', RTGETOPT_REQ_STRING }, + { "--fingerprint", 'p', RTGETOPT_REQ_STRING }, + { "--keyfile", 'k', RTGETOPT_REQ_STRING }, + { "--passphrase", 'P', RTGETOPT_REQ_STRING }, + { "--tenancy", 't', RTGETOPT_REQ_STRING }, + { "--compartment", 'c', RTGETOPT_REQ_STRING }, + { "--region", 'r', RTGETOPT_REQ_STRING } + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + com::SafeArray<BSTR> names; + com::SafeArray<BSTR> values; + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'u': // --clouduser + Bstr("user").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'p': // --fingerprint + Bstr("fingerprint").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'k': // --keyfile + Bstr("key_file").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'P': // --passphrase + Bstr("pass_phrase").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 't': // --tenancy + Bstr("tenancy").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'c': // --compartment + Bstr("compartment").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'r': // --region + Bstr("region").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* check for required options */ + if (bstrProvider.isEmpty()) + return errorSyntax(Misc::tr("Parameter --provider is required")); + if (bstrProfile.isEmpty()) + return errorSyntax(Misc::tr("Parameter --profile is required")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProvider> pCloudProvider; + + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProfile> pCloudProfile; + + if (pCloudProvider) + { + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(bstrProfile.raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + CHECK_ERROR2_RET(hrc, pCloudProfile, + SetProperties(ComSafeArrayAsInParam(names), ComSafeArrayAsInParam(values)), + RTEXITCODE_FAILURE); + } + + CHECK_ERROR2(hrc, pCloudProvider, SaveProfiles()); + + RTPrintf(Misc::tr("Provider %ls: profile '%ls' was updated.\n"),bstrProvider.raw(), bstrProfile.raw()); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/** + * Gets the properties of cloud profile + * + * @returns 0 on success, 1 on failure + */ +static RTEXITCODE showCloudProfileProperties(HandlerArg *a, PCLOUDPROFILECOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + Bstr bstrProvider(pCommonOpts->pszProviderName); + Bstr bstrProfile(pCommonOpts->pszProfileName); + + /* check for required options */ + if (bstrProvider.isEmpty()) + return errorSyntax(Misc::tr("Parameter --provider is required")); + if (bstrProfile.isEmpty()) + return errorSyntax(Misc::tr("Parameter --profile is required")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProfile> pCloudProfile; + if (pCloudProvider) + { + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(bstrProfile.raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + + Bstr bstrProviderID; + pCloudProfile->COMGETTER(ProviderId)(bstrProviderID.asOutParam()); + RTPrintf(Misc::tr("Provider GUID: %ls\n"), bstrProviderID.raw()); + + com::SafeArray<BSTR> names; + com::SafeArray<BSTR> values; + CHECK_ERROR2_RET(hrc, pCloudProfile, + GetProperties(Bstr().raw(), ComSafeArrayAsOutParam(names), ComSafeArrayAsOutParam(values)), + RTEXITCODE_FAILURE); + size_t cNames = names.size(); + size_t cValues = values.size(); + bool fFirst = true; + for (size_t k = 0; k < cNames; k++) + { + Bstr value; + if (k < cValues) + value = values[k]; + RTPrintf("%s%ls=%ls\n", + fFirst ? Misc::tr("Property: ") : " ", + names[k], value.raw()); + fFirst = false; + } + + RTPrintf("\n"); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE addCloudProfile(HandlerArg *a, int iFirst, PCLOUDPROFILECOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + Bstr bstrProvider(pCommonOpts->pszProviderName); + Bstr bstrProfile(pCommonOpts->pszProfileName); + + + /* check for required options */ + if (bstrProvider.isEmpty()) + return errorSyntax(Misc::tr("Parameter --provider is required")); + if (bstrProfile.isEmpty()) + return errorSyntax(Misc::tr("Parameter --profile is required")); + + /* + * Parse options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--clouduser", 'u', RTGETOPT_REQ_STRING }, + { "--fingerprint", 'p', RTGETOPT_REQ_STRING }, + { "--keyfile", 'k', RTGETOPT_REQ_STRING }, + { "--passphrase", 'P', RTGETOPT_REQ_STRING }, + { "--tenancy", 't', RTGETOPT_REQ_STRING }, + { "--compartment", 'c', RTGETOPT_REQ_STRING }, + { "--region", 'r', RTGETOPT_REQ_STRING } + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), iFirst, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + com::SafeArray<BSTR> names; + com::SafeArray<BSTR> values; + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'u': // --clouduser + Bstr("user").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'p': // --fingerprint + Bstr("fingerprint").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'k': // --keyfile + Bstr("key_file").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'P': // --passphrase + Bstr("pass_phrase").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 't': // --tenancy + Bstr("tenancy").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'c': // --compartment + Bstr("compartment").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + case 'r': // --region + Bstr("region").detachTo(names.appendedRaw()); + Bstr(ValueUnion.psz).detachTo(values.appendedRaw()); + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, pCloudProvider, + CreateProfile(bstrProfile.raw(), + ComSafeArrayAsInParam(names), + ComSafeArrayAsInParam(values)), + RTEXITCODE_FAILURE); + + CHECK_ERROR2(hrc, pCloudProvider, SaveProfiles()); + + RTPrintf(Misc::tr("Provider %ls: profile '%ls' was added.\n"),bstrProvider.raw(), bstrProfile.raw()); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE deleteCloudProfile(HandlerArg *a, PCLOUDPROFILECOMMONOPT pCommonOpts) +{ + HRESULT hrc = S_OK; + + Bstr bstrProvider(pCommonOpts->pszProviderName); + Bstr bstrProfile(pCommonOpts->pszProfileName); + + /* check for required options */ + if (bstrProvider.isEmpty()) + return errorSyntax(Misc::tr("Parameter --provider is required")); + if (bstrProfile.isEmpty()) + return errorSyntax(Misc::tr("Parameter --profile is required")); + + ComPtr<IVirtualBox> pVirtualBox = a->virtualBox; + ComPtr<ICloudProviderManager> pCloudProviderManager; + CHECK_ERROR2_RET(hrc, pVirtualBox, + COMGETTER(CloudProviderManager)(pCloudProviderManager.asOutParam()), + RTEXITCODE_FAILURE); + ComPtr<ICloudProvider> pCloudProvider; + CHECK_ERROR2_RET(hrc, pCloudProviderManager, + GetProviderByShortName(bstrProvider.raw(), pCloudProvider.asOutParam()), + RTEXITCODE_FAILURE); + + ComPtr<ICloudProfile> pCloudProfile; + if (pCloudProvider) + { + CHECK_ERROR2_RET(hrc, pCloudProvider, + GetProfileByName(bstrProfile.raw(), pCloudProfile.asOutParam()), + RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, pCloudProfile, + Remove(), + RTEXITCODE_FAILURE); + + CHECK_ERROR2_RET(hrc, pCloudProvider, + SaveProfiles(), + RTEXITCODE_FAILURE); + + RTPrintf(Misc::tr("Provider %ls: profile '%ls' was deleted.\n"), bstrProvider.raw(), bstrProfile.raw()); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleCloudProfile(HandlerArg *a) +{ + if (a->argc < 1) + return errorNoSubcommand(); + + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--provider", 'v', RTGETOPT_REQ_STRING }, + { "--profile", 'f', RTGETOPT_REQ_STRING }, + /* subcommands */ + { "add", 1000, RTGETOPT_REQ_NOTHING }, + { "show", 1001, RTGETOPT_REQ_NOTHING }, + { "update", 1002, RTGETOPT_REQ_NOTHING }, + { "delete", 1003, RTGETOPT_REQ_NOTHING }, + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + CLOUDPROFILECOMMONOPT CommonOpts = { NULL, NULL }; + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'v': // --provider + CommonOpts.pszProviderName = ValueUnion.psz; + break; + case 'f': // --profile + CommonOpts.pszProfileName = ValueUnion.psz; + break; + /* Sub-commands: */ + case 1000: + setCurrentSubcommand(HELP_SCOPE_CLOUDPROFILE_ADD); + return addCloudProfile(a, GetState.iNext, &CommonOpts); + case 1001: + setCurrentSubcommand(HELP_SCOPE_CLOUDPROFILE_SHOW); + return showCloudProfileProperties(a, &CommonOpts); + case 1002: + setCurrentSubcommand(HELP_SCOPE_CLOUDPROFILE_UPDATE); + return setCloudProfileProperties(a, GetState.iNext, &CommonOpts); + case 1003: + setCurrentSubcommand(HELP_SCOPE_CLOUDPROFILE_DELETE); + return deleteCloudProfile(a, &CommonOpts); + case VINF_GETOPT_NOT_OPTION: + return errorUnknownSubcommand(ValueUnion.psz); + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + return errorNoSubcommand(); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageModifyNvram.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageModifyNvram.cpp new file mode 100644 index 00000000..d36bed08 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageModifyNvram.cpp @@ -0,0 +1,582 @@ +/* $Id: VBoxManageModifyNvram.cpp $ */ +/** @file + * VBoxManage - The nvram control related commands. + */ + +/* + * Copyright (C) 2021-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/errcore.h> +#include <iprt/path.h> +#include <iprt/param.h> +#include <iprt/string.h> +#include <iprt/ctype.h> +#include <iprt/stream.h> +#include <iprt/file.h> +#include <iprt/getopt.h> +#include <iprt/uuid.h> +#include <VBox/log.h> + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Nvram); + +// funcs +/////////////////////////////////////////////////////////////////////////////// + + +/** + * Handles the 'modifynvram myvm inituefivarstore' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramInitUefiVarStore(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + RT_NOREF(a); + + CHECK_ERROR2I_RET(nvramStore, InitUefiVariableStore(0 /*aSize*/), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + + +/** + * Handles the 'modifynvram myvm enrollmssignatures' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramEnrollMsSignatures(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + RT_NOREF(a); + + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + + CHECK_ERROR2I_RET(uefiVarStore, EnrollDefaultMsSignatures(), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + + +/** + * Helper for handleModifyNvramEnrollPlatformKey() and handleModifyNvramEnrollMok(). + * + * This function reads key from file and enrolls it either as a PK (Platform Key) + * or as a MOK (Machine Owner Key). + * + * @returns Exit code. + * @param pszKey Path to a file which contains the key. + * @param pszOwnerUuid Owner's UUID. + * @param nvramStore Reference to the NVRAM store interface. + * @param fPk If True, a key will be enrolled as a PK, otherwise as a MOK. + */ +static RTEXITCODE handleModifyNvramEnrollPlatformKeyOrMok(const char *pszKey, const char *pszOwnerUuid, + ComPtr<INvramStore> &nvramStore, bool fPk) +{ + RTFILE hKeyFile; + + int vrc = RTFileOpen(&hKeyFile, pszKey, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_SUCCESS(vrc)) + { + uint64_t cbSize; + vrc = RTFileQuerySize(hKeyFile, &cbSize); + if (RT_SUCCESS(vrc)) + { + if (cbSize <= _32K) + { + SafeArray<BYTE> aKey((size_t)cbSize); + vrc = RTFileRead(hKeyFile, aKey.raw(), (size_t)cbSize, NULL); + if (RT_SUCCESS(vrc)) + { + RTFileClose(hKeyFile); + + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + if (fPk) + CHECK_ERROR2I_RET(uefiVarStore, EnrollPlatformKey(ComSafeArrayAsInParam(aKey), Bstr(pszOwnerUuid).raw()), RTEXITCODE_FAILURE); + else + CHECK_ERROR2I_RET(uefiVarStore, AddSignatureToMok(ComSafeArrayAsInParam(aKey), Bstr(pszOwnerUuid).raw(), SignatureType_X509), RTEXITCODE_FAILURE); + + return RTEXITCODE_SUCCESS; + } + else + RTMsgError(Nvram::tr("Cannot read contents of file \"%s\": %Rrc"), pszKey, vrc); + } + else + RTMsgError(Nvram::tr("File \"%s\" is bigger than 32KByte"), pszKey); + } + else + RTMsgError(Nvram::tr("Cannot get size of file \"%s\": %Rrc"), pszKey, vrc); + + RTFileClose(hKeyFile); + } + else + RTMsgError(Nvram::tr("Cannot open file \"%s\": %Rrc"), pszKey, vrc); + + return RTEXITCODE_FAILURE; +} + + +/** + * Handles the 'modifynvram myvm enrollpk' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvramStore Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramEnrollPlatformKey(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--platform-key", 'p', RTGETOPT_REQ_STRING }, + { "--owner-uuid", 'f', RTGETOPT_REQ_STRING } + }; + + const char *pszPlatformKey = NULL; + const char *pszOwnerUuid = NULL; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'p': + pszPlatformKey = ValueUnion.psz; + break; + case 'f': + pszOwnerUuid = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszPlatformKey) + return errorSyntax(Nvram::tr("No platform key file path was given to \"enrollpk\"")); + if (!pszOwnerUuid) + return errorSyntax(Nvram::tr("No owner UUID was given to \"enrollpk\"")); + + return handleModifyNvramEnrollPlatformKeyOrMok(pszPlatformKey, pszOwnerUuid, nvramStore, true /* fPk */); +} + + +/** + * Handles the 'modifynvram myvm enrollmok' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvramStore Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramEnrollMok(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--mok", 'p', RTGETOPT_REQ_STRING }, + { "--owner-uuid", 'f', RTGETOPT_REQ_STRING } + }; + + const char *pszMok = NULL; + const char *pszOwnerUuid = NULL; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'p': + pszMok = ValueUnion.psz; + break; + case 'f': + pszOwnerUuid = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszMok) + return errorSyntax(Nvram::tr("No machine owner key file path was given to \"enrollpk\"")); + if (!pszOwnerUuid) + return errorSyntax(Nvram::tr("No owner UUID was given to \"enrollpk\"")); + + return handleModifyNvramEnrollPlatformKeyOrMok(pszMok, pszOwnerUuid, nvramStore, false /* fPk */); +} + + +/** + * Handles the 'modifynvram myvm enrollorclpk' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramEnrollOraclePlatformKey(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + RT_NOREF(a); + + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + + CHECK_ERROR2I_RET(uefiVarStore, EnrollOraclePlatformKey(), RTEXITCODE_FAILURE); + return RTEXITCODE_SUCCESS; +} + + +/** + * Handles the 'modifynvram myvm listvars' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramListUefiVars(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + RT_NOREF(a); + + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + + com::SafeArray<BSTR> aNames; + com::SafeArray<BSTR> aOwnerGuids; + CHECK_ERROR2I_RET(uefiVarStore, QueryVariables(ComSafeArrayAsOutParam(aNames), ComSafeArrayAsOutParam(aOwnerGuids)), RTEXITCODE_FAILURE); + for (size_t i = 0; i < aNames.size(); i++) + { + Bstr strName = aNames[i]; + Bstr strOwnerGuid = aOwnerGuids[i]; + + RTPrintf("%-32ls {%ls}\n", strName.raw(), strOwnerGuid.raw()); + } + + return RTEXITCODE_SUCCESS; +} + + +/** + * Handles the 'modifynvram myvm queryvar' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramQueryUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--filename", 'f', RTGETOPT_REQ_STRING } + }; + + const char *pszVarName = NULL; + const char *pszVarDataFilename = NULL; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': + pszVarName = ValueUnion.psz; + break; + case 'f': + pszVarDataFilename = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszVarName) + return errorSyntax(Nvram::tr("No variable name was given to \"queryvar\"")); + + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + + Bstr strOwnerGuid; + com::SafeArray<UefiVariableAttributes_T> aVarAttrs; + com::SafeArray<BYTE> aData; + CHECK_ERROR2I_RET(uefiVarStore, QueryVariableByName(Bstr(pszVarName).raw(), strOwnerGuid.asOutParam(), + ComSafeArrayAsOutParam(aVarAttrs), ComSafeArrayAsOutParam(aData)), + RTEXITCODE_FAILURE); + + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + if (!pszVarDataFilename) + { + RTPrintf("%s {%ls}:\n" + "%.*Rhxd\n", pszVarName, strOwnerGuid.raw(), aData.size(), aData.raw()); + } + else + { + /* Just write the data to the file. */ + RTFILE hFile = NIL_RTFILE; + vrc = RTFileOpen(&hFile, pszVarDataFilename, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); + if (RT_SUCCESS(vrc)) + { + vrc = RTFileWrite(hFile, aData.raw(), aData.size(), NULL /*pcbWritten*/); + if (RT_FAILURE(vrc)) + rcExit = RTMsgErrorExitFailure(Nvram::tr("Error writing to '%s': %Rrc"), pszVarDataFilename, vrc); + + RTFileClose(hFile); + } + else + rcExit = RTMsgErrorExitFailure(Nvram::tr("Error opening '%s': %Rrc"), pszVarDataFilename, vrc); + } + + return rcExit; +} + + +/** + * Handles the 'modifynvram myvm deletevar' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramDeleteUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--owner-uuid", 'f', RTGETOPT_REQ_STRING } + }; + + const char *pszVarName = NULL; + const char *pszOwnerUuid = NULL; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': + pszVarName = ValueUnion.psz; + break; + case 'f': + pszOwnerUuid = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszVarName) + return errorSyntax(Nvram::tr("No variable name was given to \"deletevar\"")); + if (!pszOwnerUuid) + return errorSyntax(Nvram::tr("No owner UUID was given to \"deletevar\"")); + + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR2I_RET(uefiVarStore, DeleteVariable(Bstr(pszVarName).raw(), Bstr(pszOwnerUuid).raw()), RTEXITCODE_FAILURE); + + return RTEXITCODE_SUCCESS; +} + + +/** + * Handles the 'modifynvram myvm changevar' sub-command. + * @returns Exit code. + * @param a The handler argument package. + * @param nvram Reference to the NVRAM store interface. + */ +static RTEXITCODE handleModifyNvramChangeUefiVar(HandlerArg *a, ComPtr<INvramStore> &nvramStore) +{ + static const RTGETOPTDEF s_aOptions[] = + { + /* common options */ + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--filename", 'f', RTGETOPT_REQ_STRING } + }; + + const char *pszVarName = NULL; + const char *pszVarDataFilename = NULL; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, a->argc - 2, &a->argv[2], s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': + pszVarName = ValueUnion.psz; + break; + case 'f': + pszVarDataFilename = ValueUnion.psz; + break; + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pszVarName) + return errorSyntax(Nvram::tr("No variable name was given to \"changevar\"")); + if (!pszVarDataFilename) + return errorSyntax(Nvram::tr("No variable data filename was given to \"changevar\"")); + + RTFILE hFile = NIL_RTFILE; + RTEXITCODE rcExit = RTEXITCODE_SUCCESS; + vrc = RTFileOpen(&hFile, pszVarDataFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE); + if (RT_SUCCESS(vrc)) + { + uint64_t cbFile = 0; + vrc = RTFileQuerySize(hFile, &cbFile); + if (RT_SUCCESS(vrc)) + { + com::SafeArray<BYTE> aData; + aData.resize(cbFile); + + vrc = RTFileRead(hFile, aData.raw(), aData.size(), NULL /*pcbRead*/); + RTFileClose(hFile); + + if (RT_SUCCESS(vrc)) + { + ComPtr<IUefiVariableStore> uefiVarStore; + CHECK_ERROR2I_RET(nvramStore, COMGETTER(UefiVariableStore)(uefiVarStore.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR2I_RET(uefiVarStore, ChangeVariable(Bstr(pszVarName).raw(), ComSafeArrayAsInParam(aData)), RTEXITCODE_FAILURE); + } + else + rcExit = RTMsgErrorExitFailure(Nvram::tr("Error reading from '%s': %Rrc"), pszVarDataFilename, vrc); + } + } + else + rcExit = RTMsgErrorExitFailure(Nvram::tr("Error opening '%s': %Rrc"), pszVarDataFilename, vrc); + + return rcExit; +} + + +/** + * Handles the 'modifynvram' command. + * @returns Exit code. + * @param a The handler argument package. + */ +RTEXITCODE handleModifyNvram(HandlerArg *a) +{ + HRESULT hrc = S_OK; + ComPtr<IMachine> machine; + ComPtr<INvramStore> nvramStore; + + if (a->argc < 2) + return errorNoSubcommand(); + + /* try to find the given machine */ + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + + /* open a session for the VM (new or shared) */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + hrc = machine->COMGETTER(NonVolatileStore)(nvramStore.asOutParam()); + if (FAILED(hrc)) goto leave; + + if (!strcmp(a->argv[1], "inituefivarstore")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_INITUEFIVARSTORE); + hrc = handleModifyNvramInitUefiVarStore(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "enrollmssignatures")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLMSSIGNATURES); + hrc = handleModifyNvramEnrollMsSignatures(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "enrollpk")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLPK); + hrc = handleModifyNvramEnrollPlatformKey(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "enrollmok")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLMOK); + hrc = handleModifyNvramEnrollMok(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "enrollorclpk")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_ENROLLORCLPK); + hrc = handleModifyNvramEnrollOraclePlatformKey(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "listvars")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_LISTVARS); + hrc = handleModifyNvramListUefiVars(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "queryvar")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_QUERYVAR); + hrc = handleModifyNvramQueryUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "deletevar")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_DELETEVAR); + hrc = handleModifyNvramDeleteUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "changevar")) + { + setCurrentSubcommand(HELP_SCOPE_MODIFYNVRAM_CHANGEVAR); + hrc = handleModifyNvramChangeUefiVar(a, nvramStore) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else + return errorUnknownSubcommand(a->argv[0]); + + /* commit changes */ + if (SUCCEEDED(hrc)) + CHECK_ERROR(machine, SaveSettings()); + +leave: + /* it's important to always close sessions */ + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp new file mode 100644 index 00000000..4a360725 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp @@ -0,0 +1,3646 @@ +/* $Id: VBoxManageModifyVM.cpp $ */ +/** @file + * VBoxManage - Implementation of modifyvm command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/cidr.h> +#include <iprt/ctype.h> +#include <iprt/file.h> +#include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/getopt.h> +#include <VBox/log.h> +#include "VBoxManage.h" +#include "VBoxManageUtils.h" + +DECLARE_TRANSLATION_CONTEXT(ModifyVM); + +using namespace com; +/** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM. */ +#if defined(_MSC_VER) +# pragma optimize("g", off) +# if _MSC_VER < RT_MSC_VER_VC120 +# pragma warning(disable:4748) +# endif +#endif + +enum +{ + MODIFYVM_NAME = 1000, + MODIFYVM_GROUPS, + MODIFYVM_DESCRIPTION, + MODIFYVM_OSTYPE, + MODIFYVM_ICONFILE, + MODIFYVM_MEMORY, + MODIFYVM_PAGEFUSION, + MODIFYVM_VRAM, + MODIFYVM_FIRMWARE, + MODIFYVM_ACPI, + MODIFYVM_IOAPIC, + MODIFYVM_PAE, + MODIFYVM_LONGMODE, + MODIFYVM_CPUID_PORTABILITY, + MODIFYVM_TFRESET, + MODIFYVM_APIC, + MODIFYVM_X2APIC, + MODIFYVM_PARAVIRTPROVIDER, + MODIFYVM_PARAVIRTDEBUG, + MODIFYVM_HWVIRTEX, + MODIFYVM_NESTEDPAGING, + MODIFYVM_LARGEPAGES, + MODIFYVM_VTXVPID, + MODIFYVM_VTXUX, + MODIFYVM_VIRT_VMSAVE_VMLOAD, + MODIFYVM_IBPB_ON_VM_EXIT, + MODIFYVM_IBPB_ON_VM_ENTRY, + MODIFYVM_SPEC_CTRL, + MODIFYVM_L1D_FLUSH_ON_SCHED, + MODIFYVM_L1D_FLUSH_ON_VM_ENTRY, + MODIFYVM_MDS_CLEAR_ON_SCHED, + MODIFYVM_MDS_CLEAR_ON_VM_ENTRY, + MODIFYVM_NESTED_HW_VIRT, + MODIFYVM_CPUS, + MODIFYVM_CPUHOTPLUG, + MODIFYVM_CPU_PROFILE, + MODIFYVM_PLUGCPU, + MODIFYVM_UNPLUGCPU, + MODIFYVM_SETCPUID, + MODIFYVM_DELCPUID, + MODIFYVM_DELCPUID_OLD, // legacy, different syntax from MODIFYVM_DELCPUID + MODIFYVM_DELALLCPUID, + MODIFYVM_GRAPHICSCONTROLLER, + MODIFYVM_MONITORCOUNT, + MODIFYVM_ACCELERATE3D, +#ifdef VBOX_WITH_VIDEOHWACCEL + MODIFYVM_ACCELERATE2DVIDEO, +#endif + MODIFYVM_BIOSLOGOFADEIN, + MODIFYVM_BIOSLOGOFADEOUT, + MODIFYVM_BIOSLOGODISPLAYTIME, + MODIFYVM_BIOSLOGOIMAGEPATH, + MODIFYVM_BIOSBOOTMENU, + MODIFYVM_BIOSAPIC, + MODIFYVM_BIOSSYSTEMTIMEOFFSET, + MODIFYVM_BIOSPXEDEBUG, + MODIFYVM_SYSTEMUUIDLE, + MODIFYVM_BOOT, + MODIFYVM_HDA, // deprecated + MODIFYVM_HDB, // deprecated + MODIFYVM_HDD, // deprecated + MODIFYVM_IDECONTROLLER, // deprecated + MODIFYVM_SATAPORTCOUNT, // deprecated + MODIFYVM_SATAPORT, // deprecated + MODIFYVM_SATA, // deprecated + MODIFYVM_SCSIPORT, // deprecated + MODIFYVM_SCSITYPE, // deprecated + MODIFYVM_SCSI, // deprecated + MODIFYVM_DVDPASSTHROUGH, // deprecated + MODIFYVM_DVD, // deprecated + MODIFYVM_FLOPPY, // deprecated + MODIFYVM_NICTRACEFILE, + MODIFYVM_NICTRACE, + MODIFYVM_NICPROPERTY, + MODIFYVM_NICTYPE, + MODIFYVM_NICSPEED, + MODIFYVM_NICBOOTPRIO, + MODIFYVM_NICPROMISC, + MODIFYVM_NICBWGROUP, + MODIFYVM_NIC, + MODIFYVM_CABLECONNECTED, + MODIFYVM_BRIDGEADAPTER, +#ifdef VBOX_WITH_CLOUD_NET + MODIFYVM_CLOUDNET, +#endif /* VBOX_WITH_CLOUD_NET */ + MODIFYVM_HOSTONLYADAPTER, +#ifdef VBOX_WITH_VMNET + MODIFYVM_HOSTONLYNET, +#endif /* VBOX_WITH_VMNET */ + MODIFYVM_INTNET, + MODIFYVM_GENERICDRV, + MODIFYVM_NATNETWORKNAME, + MODIFYVM_NATNET, + MODIFYVM_NATBINDIP, + MODIFYVM_NATSETTINGS, + MODIFYVM_NATPF, + MODIFYVM_NATALIASMODE, + MODIFYVM_NATTFTPPREFIX, + MODIFYVM_NATTFTPFILE, + MODIFYVM_NATTFTPSERVER, + MODIFYVM_NATDNSPASSDOMAIN, + MODIFYVM_NATDNSPROXY, + MODIFYVM_NATDNSHOSTRESOLVER, + MODIFYVM_NATLOCALHOSTREACHABLE, + MODIFYVM_MACADDRESS, + MODIFYVM_HIDPTR, + MODIFYVM_HIDKBD, + MODIFYVM_UARTMODE, + MODIFYVM_UARTTYPE, + MODIFYVM_UART, +#if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS) + MODIFYVM_LPTMODE, + MODIFYVM_LPT, +#endif + MODIFYVM_GUESTMEMORYBALLOON, + MODIFYVM_AUDIOCONTROLLER, + MODIFYVM_AUDIOCODEC, + MODIFYVM_AUDIODRIVER, + MODIFYVM_AUDIOENABLED, + MODIFYVM_AUDIO, /* Deprecated; remove in the next major version. */ + MODIFYVM_AUDIOIN, + MODIFYVM_AUDIOOUT, +#ifdef VBOX_WITH_SHARED_CLIPBOARD + MODIFYVM_CLIPBOARD_MODE, +# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS + MODIFYVM_CLIPBOARD_FILE_TRANSFERS, +# endif +#endif + MODIFYVM_DRAGANDDROP, + MODIFYVM_VRDPPORT, /* VRDE: deprecated */ + MODIFYVM_VRDPADDRESS, /* VRDE: deprecated */ + MODIFYVM_VRDPAUTHTYPE, /* VRDE: deprecated */ + MODIFYVM_VRDPMULTICON, /* VRDE: deprecated */ + MODIFYVM_VRDPREUSECON, /* VRDE: deprecated */ + MODIFYVM_VRDPVIDEOCHANNEL, /* VRDE: deprecated */ + MODIFYVM_VRDPVIDEOCHANNELQUALITY, /* VRDE: deprecated */ + MODIFYVM_VRDP, /* VRDE: deprecated */ + MODIFYVM_VRDEPROPERTY, + MODIFYVM_VRDEPORT, + MODIFYVM_VRDEADDRESS, + MODIFYVM_VRDEAUTHTYPE, + MODIFYVM_VRDEAUTHLIBRARY, + MODIFYVM_VRDEMULTICON, + MODIFYVM_VRDEREUSECON, + MODIFYVM_VRDEVIDEOCHANNEL, + MODIFYVM_VRDEVIDEOCHANNELQUALITY, + MODIFYVM_VRDE_EXTPACK, + MODIFYVM_VRDE, + MODIFYVM_RTCUSEUTC, + MODIFYVM_USBRENAME, + MODIFYVM_USBXHCI, + MODIFYVM_USBEHCI, + MODIFYVM_USBOHCI, + MODIFYVM_SNAPSHOTFOLDER, + MODIFYVM_TELEPORTER_ENABLED, + MODIFYVM_TELEPORTER_PORT, + MODIFYVM_TELEPORTER_ADDRESS, + MODIFYVM_TELEPORTER_PASSWORD, + MODIFYVM_TELEPORTER_PASSWORD_FILE, + MODIFYVM_TRACING_ENABLED, + MODIFYVM_TRACING_CONFIG, + MODIFYVM_TRACING_ALLOW_VM_ACCESS, + MODIFYVM_HARDWARE_UUID, + MODIFYVM_HPET, + MODIFYVM_IOCACHE, + MODIFYVM_IOCACHESIZE, + MODIFYVM_CPU_EXECTUION_CAP, + MODIFYVM_AUTOSTART_ENABLED, + MODIFYVM_AUTOSTART_DELAY, + MODIFYVM_AUTOSTOP_TYPE, +#ifdef VBOX_WITH_PCI_PASSTHROUGH + MODIFYVM_ATTACH_PCI, + MODIFYVM_DETACH_PCI, +#endif +#ifdef VBOX_WITH_USB_CARDREADER + MODIFYVM_USBCARDREADER, +#endif +#ifdef VBOX_WITH_RECORDING + MODIFYVM_RECORDING, + MODIFYVM_RECORDING_FEATURES, + MODIFYVM_RECORDING_SCREENS, + MODIFYVM_RECORDING_FILENAME, + MODIFYVM_RECORDING_VIDEO_WIDTH, + MODIFYVM_RECORDING_VIDEO_HEIGHT, + MODIFYVM_RECORDING_VIDEO_RES, + MODIFYVM_RECORDING_VIDEO_RATE, + MODIFYVM_RECORDING_VIDEO_FPS, + MODIFYVM_RECORDING_MAXTIME, + MODIFYVM_RECORDING_MAXSIZE, + MODIFYVM_RECORDING_OPTIONS, +#endif + MODIFYVM_CHIPSET, +#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL) + MODIFYVM_IOMMU, +#endif +#if defined(VBOX_WITH_TPM) + MODIFYVM_TPM_LOCATION, + MODIFYVM_TPM_TYPE, +#endif + MODIFYVM_DEFAULTFRONTEND, + MODIFYVM_VMPROC_PRIORITY, + MODIFYVM_TESTING_ENABLED, + MODIFYVM_TESTING_MMIO, + MODIFYVM_TESTING_CFG_DWORD, + MODIFYVM_GUEST_DEBUG_PROVIDER, + MODIFYVM_GUEST_DEBUG_IO_PROVIDER, + MODIFYVM_GUEST_DEBUG_ADDRESS, + MODIFYVM_GUEST_DEBUG_PORT, +}; + +static const RTGETOPTDEF g_aModifyVMOptions[] = +{ + OPT1("--name", MODIFYVM_NAME, RTGETOPT_REQ_STRING), + OPT1("--groups", MODIFYVM_GROUPS, RTGETOPT_REQ_STRING), + OPT1("--description", MODIFYVM_DESCRIPTION, RTGETOPT_REQ_STRING), + OPT2("--os-type", "--ostype", MODIFYVM_OSTYPE, RTGETOPT_REQ_STRING), + OPT2("--icon-file", "--iconfile", MODIFYVM_ICONFILE, RTGETOPT_REQ_STRING), + OPT1("--memory", MODIFYVM_MEMORY, RTGETOPT_REQ_UINT32), + OPT2("--page-fusion", "--pagefusion", MODIFYVM_PAGEFUSION, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--vram", MODIFYVM_VRAM, RTGETOPT_REQ_UINT32), + OPT1("--firmware", MODIFYVM_FIRMWARE, RTGETOPT_REQ_STRING), + OPT1("--acpi", MODIFYVM_ACPI, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--ioapic", MODIFYVM_IOAPIC, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--pae", MODIFYVM_PAE, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--long-mode", "--longmode", MODIFYVM_LONGMODE, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--cpuid-portability-level", MODIFYVM_CPUID_PORTABILITY, RTGETOPT_REQ_UINT32), + OPT2("--triple-fault-reset", "--triplefaultreset", MODIFYVM_TFRESET, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--apic", MODIFYVM_APIC, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--x2apic", MODIFYVM_X2APIC, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--paravirt-provider", "--paravirtprovider", MODIFYVM_PARAVIRTPROVIDER, RTGETOPT_REQ_STRING), + OPT2("--paravirt-debug", "--paravirtdebug", MODIFYVM_PARAVIRTDEBUG, RTGETOPT_REQ_STRING), + OPT1("--hwvirtex", MODIFYVM_HWVIRTEX, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--nested-paging", "--nestedpaging", MODIFYVM_NESTEDPAGING, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--large-pages", "--largepages", MODIFYVM_LARGEPAGES, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--vtx-vpid", "--vtxvpid", MODIFYVM_VTXVPID, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--vtx-ux", "--vtxux", MODIFYVM_VTXUX, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--virt-vmsave-vmload", MODIFYVM_VIRT_VMSAVE_VMLOAD, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--ibpb-on-vm-exit", MODIFYVM_IBPB_ON_VM_EXIT, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--ibpb-on-vm-entry", MODIFYVM_IBPB_ON_VM_ENTRY, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--spec-ctrl", MODIFYVM_SPEC_CTRL, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--l1d-flush-on-sched", MODIFYVM_L1D_FLUSH_ON_SCHED, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--l1d-flush-on-vm-entry", MODIFYVM_L1D_FLUSH_ON_VM_ENTRY, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--mds-clear-on-sched", MODIFYVM_MDS_CLEAR_ON_SCHED, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--mds-clear-on-vm-entry", MODIFYVM_MDS_CLEAR_ON_VM_ENTRY, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--nested-hw-virt", MODIFYVM_NESTED_HW_VIRT, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--cpuid-set", "--cpuidset", MODIFYVM_SETCPUID, RTGETOPT_REQ_UINT32_OPTIONAL_PAIR | RTGETOPT_FLAG_HEX), + OPT1("--cpuid-remove", MODIFYVM_DELCPUID, RTGETOPT_REQ_UINT32_OPTIONAL_PAIR | RTGETOPT_FLAG_HEX), + OPT1("--cpuidremove", MODIFYVM_DELCPUID_OLD, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX), /* legacy - syntax differs */ + OPT2("--cpuid-remove-all", "--cpuidremoveall", MODIFYVM_DELALLCPUID, RTGETOPT_REQ_NOTHING), + OPT1("--cpus", MODIFYVM_CPUS, RTGETOPT_REQ_UINT32), + OPT2("--cpu-hotplug", "--cpuhotplug", MODIFYVM_CPUHOTPLUG, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--cpu-profile", MODIFYVM_CPU_PROFILE, RTGETOPT_REQ_STRING), + OPT2("--plug-cpu", "--plugcpu", MODIFYVM_PLUGCPU, RTGETOPT_REQ_UINT32), + OPT2("--unplug-cpu", "--unplugcpu", MODIFYVM_UNPLUGCPU, RTGETOPT_REQ_UINT32), + OPT2("--cpu-execution-cap", "--cpuexecutioncap", MODIFYVM_CPU_EXECTUION_CAP, RTGETOPT_REQ_UINT32), + OPT2("--rtc-use-utc", "--rtcuseutc", MODIFYVM_RTCUSEUTC, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--graphicscontroller", "--graphicscontroller", MODIFYVM_GRAPHICSCONTROLLER, RTGETOPT_REQ_STRING), + OPT2("--monitor-count", "--monitorcount", MODIFYVM_MONITORCOUNT, RTGETOPT_REQ_UINT32), + OPT2("--accelerate-3d", "--accelerate3d", MODIFYVM_ACCELERATE3D, RTGETOPT_REQ_BOOL_ONOFF), +#ifdef VBOX_WITH_VIDEOHWACCEL + OPT2("--accelerate-2d-video", "--accelerate2dvideo", MODIFYVM_ACCELERATE2DVIDEO, RTGETOPT_REQ_BOOL_ONOFF), +#endif + OPT2("--bios-logo-fade-in", "--bioslogofadein", MODIFYVM_BIOSLOGOFADEIN, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--bios-logo-fade-out", "--bioslogofadeout", MODIFYVM_BIOSLOGOFADEOUT, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--bios-logo-display-time", "--bioslogodisplaytime", MODIFYVM_BIOSLOGODISPLAYTIME, RTGETOPT_REQ_UINT32), + OPT2("--bios-logo-image-path", "--bioslogoimagepath", MODIFYVM_BIOSLOGOIMAGEPATH, RTGETOPT_REQ_STRING), + OPT2("--bios-boot-menu", "--biosbootmenu", MODIFYVM_BIOSBOOTMENU, RTGETOPT_REQ_STRING), + OPT2("--bios-system-time-offset", "--biossystemtimeoffset", MODIFYVM_BIOSSYSTEMTIMEOFFSET, RTGETOPT_REQ_INT64), + OPT2("--bios-apic", "--biosapic", MODIFYVM_BIOSAPIC, RTGETOPT_REQ_STRING), + OPT2("--bios-pxe-debug", "--biospxedebug", MODIFYVM_BIOSPXEDEBUG, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--system-uuid-le", "--system-uuid-le", MODIFYVM_SYSTEMUUIDLE, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--boot", MODIFYVM_BOOT, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT1("--hda", MODIFYVM_HDA, RTGETOPT_REQ_STRING), /* deprecated */ + OPT1("--hdb", MODIFYVM_HDB, RTGETOPT_REQ_STRING), /* deprecated */ + OPT1("--hdd", MODIFYVM_HDD, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--idec-ontroller", "--idecontroller", MODIFYVM_IDECONTROLLER, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--sata-port-count", "--sataportcount", MODIFYVM_SATAPORTCOUNT, RTGETOPT_REQ_UINT32), /* deprecated */ + OPT2("--sata-port", "--sataport", MODIFYVM_SATAPORT, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), /* deprecated */ + OPT1("--sata", MODIFYVM_SATA, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--scsi-port", "--scsiport", MODIFYVM_SCSIPORT, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), /* deprecated */ + OPT2("--scsi-type", "--scsitype", MODIFYVM_SCSITYPE, RTGETOPT_REQ_STRING), /* deprecated */ + OPT1("--scsi", MODIFYVM_SCSI, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--dvd-pass-through", "--dvdpassthrough", MODIFYVM_DVDPASSTHROUGH, RTGETOPT_REQ_STRING), /* deprecated */ + OPT1("--dvd", MODIFYVM_DVD, RTGETOPT_REQ_STRING), /* deprecated */ + OPT1("--floppy", MODIFYVM_FLOPPY, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--nic-trace-file", "--nictracefile", MODIFYVM_NICTRACEFILE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nic-trace", "--nictrace", MODIFYVM_NICTRACE, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX), + OPT2("--nic-property", "--nicproperty", MODIFYVM_NICPROPERTY, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nic-type", "--nictype", MODIFYVM_NICTYPE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nic-speed", "--nicspeed", MODIFYVM_NICSPEED, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX), + OPT2("--nic-boot-prio", "--nicbootprio", MODIFYVM_NICBOOTPRIO, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX), + OPT2("--nic-promisc", "--nicpromisc", MODIFYVM_NICPROMISC, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nic-bandwidth-group", "--nicbandwidthgroup", MODIFYVM_NICBWGROUP, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT1("--nic", MODIFYVM_NIC, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--cable-connected", "--cableconnected", MODIFYVM_CABLECONNECTED, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX), + OPT2("--bridge-adapter", "--bridgeadapter", MODIFYVM_BRIDGEADAPTER, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), +#ifdef VBOX_WITH_CLOUD_NET + OPT2("--cloud-network", "--cloudnetwork", MODIFYVM_CLOUDNET, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), +#endif /* VBOX_WITH_CLOUD_NET */ + OPT2("--host-only-adapter", "--hostonlyadapter", MODIFYVM_HOSTONLYADAPTER, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), +#ifdef VBOX_WITH_VMNET + OPT2("--host-only-net", "--hostonlynet", MODIFYVM_HOSTONLYNET, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), +#endif + OPT1("--intnet", MODIFYVM_INTNET, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nic-generic-drv", "--nicgenericdrv", MODIFYVM_GENERICDRV, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-network", "--natnetwork", MODIFYVM_NATNETWORKNAME, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-net", "--natnet", MODIFYVM_NATNET, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-bind-ip", "--natbindip", MODIFYVM_NATBINDIP, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-settings", "--natsettings", MODIFYVM_NATSETTINGS, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-pf", "--natpf", MODIFYVM_NATPF, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-alias-mode", "--nataliasmode", MODIFYVM_NATALIASMODE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-tftp-prefix", "--nattftpprefix", MODIFYVM_NATTFTPPREFIX, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-tftp-file", "--nattftpfile", MODIFYVM_NATTFTPFILE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-tftp-server", "--nattftpserver", MODIFYVM_NATTFTPSERVER, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--nat-dns-pass-domain", "--natdnspassdomain", MODIFYVM_NATDNSPASSDOMAIN, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX), + OPT2("--nat-dns-proxy", "--natdnsproxy", MODIFYVM_NATDNSPROXY, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX), + OPT2("--nat-dns-host-resolver", "--natdnshostresolver", MODIFYVM_NATDNSHOSTRESOLVER, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX), + OPT2("--nat-localhostreachable", "--natlocalhostreachable", MODIFYVM_NATLOCALHOSTREACHABLE, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX), + OPT2("--mac-address", "--macaddress", MODIFYVM_MACADDRESS, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT1("--mouse", MODIFYVM_HIDPTR, RTGETOPT_REQ_STRING), + OPT1("--keyboard", MODIFYVM_HIDKBD, RTGETOPT_REQ_STRING), + OPT2("--uart-mode", "--uartmode", MODIFYVM_UARTMODE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT2("--uart-type", "--uarttype", MODIFYVM_UARTTYPE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT1("--uart", MODIFYVM_UART, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), +#if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS) + OPT2("--lpt-mode", "--lptmode", MODIFYVM_LPTMODE, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), + OPT1("--lpt", MODIFYVM_LPT, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX), +#endif + OPT2("--guest-memory-balloon", "--guestmemoryballoon", MODIFYVM_GUESTMEMORYBALLOON, RTGETOPT_REQ_UINT32), + OPT2("--audio-controller", "--audiocontroller", MODIFYVM_AUDIOCONTROLLER, RTGETOPT_REQ_STRING), + OPT2("--audio-codec", "--audiocodec", MODIFYVM_AUDIOCODEC, RTGETOPT_REQ_STRING), + OPT1("--audio", MODIFYVM_AUDIO, RTGETOPT_REQ_STRING), + OPT2("--audio-driver", "--audiodriver", MODIFYVM_AUDIODRIVER, RTGETOPT_REQ_STRING), + OPT2("--audio-enabled", "--audioenabled", MODIFYVM_AUDIOENABLED, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--audio-in", "--audioin", MODIFYVM_AUDIOIN, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--audio-out", "--audioout", MODIFYVM_AUDIOOUT, RTGETOPT_REQ_BOOL_ONOFF), +#ifdef VBOX_WITH_SHARED_CLIPBOARD + OPT1("--clipboard-mode", MODIFYVM_CLIPBOARD_MODE, RTGETOPT_REQ_STRING), + OPT1("--clipboard", MODIFYVM_CLIPBOARD_MODE, RTGETOPT_REQ_STRING), /* deprecated */ +# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS + OPT1("--clipboard-file-transfers", MODIFYVM_CLIPBOARD_FILE_TRANSFERS, RTGETOPT_REQ_STRING), +# endif +#endif + OPT2("--drag-and-drop", "--draganddrop", MODIFYVM_DRAGANDDROP, RTGETOPT_REQ_STRING), + OPT2("--vrdp-port", "--vrdpport", MODIFYVM_VRDPPORT, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--vrdp-address", "--vrdpaddress", MODIFYVM_VRDPADDRESS, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--vrdp-auth-type", "--vrdpauthtype", MODIFYVM_VRDPAUTHTYPE, RTGETOPT_REQ_STRING), /* deprecated */ + OPT2("--vrdp-multi-con", "--vrdpmulticon", MODIFYVM_VRDPMULTICON, RTGETOPT_REQ_BOOL_ONOFF), /* deprecated */ + OPT2("--vrdp-reuse-con", "--vrdpreusecon", MODIFYVM_VRDPREUSECON, RTGETOPT_REQ_BOOL_ONOFF), /* deprecated */ + OPT2("--vrdp-video-channel", "--vrdpvideochannel", MODIFYVM_VRDPVIDEOCHANNEL, RTGETOPT_REQ_BOOL_ONOFF), /* deprecated */ + OPT2("--vrdp-video-channel-quality", "--vrdpvideochannelquality",MODIFYVM_VRDPVIDEOCHANNELQUALITY, RTGETOPT_REQ_STRING), /* deprecated */ + OPT1("--vrdp", MODIFYVM_VRDP, RTGETOPT_REQ_BOOL_ONOFF), /* deprecated */ + OPT2("--vrde-property", "--vrdeproperty", MODIFYVM_VRDEPROPERTY, RTGETOPT_REQ_STRING), + OPT2("--vrde-port", "--vrdeport", MODIFYVM_VRDEPORT, RTGETOPT_REQ_STRING), + OPT2("--vrde-address", "--vrdeaddress", MODIFYVM_VRDEADDRESS, RTGETOPT_REQ_STRING), + OPT2("--vrde-auth-type", "--vrdeauthtype", MODIFYVM_VRDEAUTHTYPE, RTGETOPT_REQ_STRING), + OPT2("--vrde-auth-library", "--vrdeauthlibrary", MODIFYVM_VRDEAUTHLIBRARY, RTGETOPT_REQ_STRING), + OPT2("--vrde-multi-con", "--vrdemulticon", MODIFYVM_VRDEMULTICON, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--vrde-reuse-con", "--vrdereusecon", MODIFYVM_VRDEREUSECON, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--vrde-video-channel", "--vrdevideochannel", MODIFYVM_VRDEVIDEOCHANNEL, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--vrde-video-channel-quality", "--vrdevideochannelquality",MODIFYVM_VRDEVIDEOCHANNELQUALITY, RTGETOPT_REQ_STRING), + OPT2("--vrde-extpack", "--vrdeextpack", MODIFYVM_VRDE_EXTPACK, RTGETOPT_REQ_STRING), + OPT1("--vrde", MODIFYVM_VRDE, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--usb-rename", "--usbrename", MODIFYVM_USBRENAME, RTGETOPT_REQ_STRING), + OPT2("--usb-xhci", "--usbxhci", MODIFYVM_USBXHCI, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--usb-ehci", "--usbehci", MODIFYVM_USBEHCI, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--usb-ohci", "--usbohci", MODIFYVM_USBOHCI, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--usb", MODIFYVM_USBOHCI, RTGETOPT_REQ_BOOL_ONOFF), /* deprecated */ + OPT2("--snapshot-folder", "--snapshotfolder", MODIFYVM_SNAPSHOTFOLDER, RTGETOPT_REQ_STRING), + OPT1("--teleporter", MODIFYVM_TELEPORTER_ENABLED, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--teleporter-enabled", "--teleporterenabled", MODIFYVM_TELEPORTER_ENABLED, RTGETOPT_REQ_BOOL_ONOFF), /* deprecated */ + OPT2("--teleporter-port", "--teleporterport", MODIFYVM_TELEPORTER_PORT, RTGETOPT_REQ_UINT32), + OPT2("--teleporter-address", "--teleporteraddress", MODIFYVM_TELEPORTER_ADDRESS, RTGETOPT_REQ_STRING), + OPT2("--teleporter-password", "--teleporterpassword", MODIFYVM_TELEPORTER_PASSWORD, RTGETOPT_REQ_STRING), + OPT2("--teleporter-password-file", "--teleporterpasswordfile", MODIFYVM_TELEPORTER_PASSWORD_FILE, RTGETOPT_REQ_STRING), + OPT1("--tracing-enabled", MODIFYVM_TRACING_ENABLED, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--tracing-config", MODIFYVM_TRACING_CONFIG, RTGETOPT_REQ_STRING), + OPT1("--tracing-allow-vm-access", MODIFYVM_TRACING_ALLOW_VM_ACCESS, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--hardware-uuid", "--hardwareuuid", MODIFYVM_HARDWARE_UUID, RTGETOPT_REQ_STRING), + OPT1("--hpet", MODIFYVM_HPET, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--iocache", MODIFYVM_IOCACHE, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--iocache-size", "--iocachesize", MODIFYVM_IOCACHESIZE, RTGETOPT_REQ_UINT32), + OPT1("--chipset", MODIFYVM_CHIPSET, RTGETOPT_REQ_STRING), +#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL) + OPT1("--iommu", MODIFYVM_IOMMU, RTGETOPT_REQ_STRING), +#endif +#if defined(VBOX_WITH_TPM) + OPT1("--tpm-type", MODIFYVM_TPM_TYPE, RTGETOPT_REQ_STRING), + OPT1("--tpm-location", MODIFYVM_TPM_LOCATION, RTGETOPT_REQ_STRING), +#endif +#ifdef VBOX_WITH_RECORDING + OPT1("--recording", MODIFYVM_RECORDING, RTGETOPT_REQ_BOOL_ONOFF), + OPT2("--recording-screens", "--recordingscreens", MODIFYVM_RECORDING_SCREENS, RTGETOPT_REQ_STRING), + OPT2("--recording-file", "--recordingfile", MODIFYVM_RECORDING_FILENAME, RTGETOPT_REQ_STRING), + OPT2("--recording-max-time", "--recordingmaxtime", MODIFYVM_RECORDING_MAXTIME, RTGETOPT_REQ_INT32), + OPT2("--recording-max-size", "--recordingmaxsize", MODIFYVM_RECORDING_MAXSIZE, RTGETOPT_REQ_INT32), + OPT2("--recording-opts", "--recordingopts", MODIFYVM_RECORDING_OPTIONS, RTGETOPT_REQ_STRING), + OPT2("--recording-options", "--recordingoptions", MODIFYVM_RECORDING_OPTIONS, RTGETOPT_REQ_STRING), + OPT2("--recording-video-res", "--recordingvideores", MODIFYVM_RECORDING_VIDEO_RES, RTGETOPT_REQ_STRING), + OPT2("--recording-video-resolution", "--recordingvideoresolution",MODIFYVM_RECORDING_VIDEO_RES, RTGETOPT_REQ_STRING), + OPT2("--recording-video-rate", "--recordingvideorate", MODIFYVM_RECORDING_VIDEO_RATE, RTGETOPT_REQ_UINT32), + OPT2("--recording-video-fps", "--recordingvideofps", MODIFYVM_RECORDING_VIDEO_FPS, RTGETOPT_REQ_UINT32), +#endif + OPT1("--autostart-enabled", MODIFYVM_AUTOSTART_ENABLED, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--autostart-delay", MODIFYVM_AUTOSTART_DELAY, RTGETOPT_REQ_UINT32), + OPT1("--autostop-type", MODIFYVM_AUTOSTOP_TYPE, RTGETOPT_REQ_STRING), +#ifdef VBOX_WITH_PCI_PASSTHROUGH + OPT2("--pci-attach", "--pciattach", MODIFYVM_ATTACH_PCI, RTGETOPT_REQ_STRING), + OPT2("--pci-detach", "--pcidetach", MODIFYVM_DETACH_PCI, RTGETOPT_REQ_STRING), +#endif +#ifdef VBOX_WITH_USB_CARDREADER + OPT2("--usb-card-reader", "--usbcardreader", MODIFYVM_USBCARDREADER, RTGETOPT_REQ_BOOL_ONOFF), +#endif + OPT2("--default-frontend", "--defaultfrontend", MODIFYVM_DEFAULTFRONTEND, RTGETOPT_REQ_STRING), + OPT1("--vm-process-priority", MODIFYVM_VMPROC_PRIORITY, RTGETOPT_REQ_STRING), + OPT1("--testing-enabled", MODIFYVM_TESTING_ENABLED, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--testing-mmio", MODIFYVM_TESTING_MMIO, RTGETOPT_REQ_BOOL_ONOFF), + OPT1("--testing-cfg-dword", MODIFYVM_TESTING_CFG_DWORD, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX), + OPT1("--guest-debug-provider", MODIFYVM_GUEST_DEBUG_PROVIDER, RTGETOPT_REQ_STRING), + OPT1("--guest-debug-io-provider", MODIFYVM_GUEST_DEBUG_IO_PROVIDER, RTGETOPT_REQ_STRING), + OPT1("--guest-debug-address", MODIFYVM_GUEST_DEBUG_ADDRESS, RTGETOPT_REQ_STRING), + OPT1("--guest-debug-port", MODIFYVM_GUEST_DEBUG_PORT, RTGETOPT_REQ_UINT32), +}; + +static void vrdeWarningDeprecatedOption(const char *pszOption) +{ + RTStrmPrintf(g_pStdErr, ModifyVM::tr("Warning: '--vrdp%s' is deprecated. Use '--vrde%s'.\n"), pszOption, pszOption); +} + + +/** + * Wrapper around IMachine::SetExtraData that does the error reporting. + * + * @returns COM result code. + * @param rSessionMachine The IMachine. + * @param pszVariable The variable to set. + * @param pszValue The value to set. To delete pass empty string, not + * NULL. + */ +static HRESULT setExtraData(ComPtr<IMachine> &rSessionMachine, const char *pszVariable, const char *pszValue) +{ + HRESULT hrc = rSessionMachine->SetExtraData(Bstr(pszVariable).raw(), Bstr(pszValue).raw()); + if (FAILED(hrc)) + { + char *pszContext = RTStrAPrintf2("IMachine::SetExtraData('%s', '%s')", pszVariable, pszValue); + com::GlueHandleComError(rSessionMachine, pszContext, hrc, __FILE__, __LINE__); + RTStrFree(pszContext); + } + return hrc; +} + + +#ifdef VBOX_WITH_PCI_PASSTHROUGH +/** Parse PCI address in format 01:02.03 and convert it to the numeric representation. */ +static int32_t parsePci(const char* szPciAddr) +{ + uint8_t aVals[3] = {0, 0, 0}; + + char *pszNext; + int vrc = RTStrToUInt8Ex(pszNext, &pszNext, 16, &aVals[0]); + if (RT_FAILURE(vrc) || pszNext == NULL || *pszNext != ':') + return -1; + + vrc = RTStrToUInt8Ex(pszNext+1, &pszNext, 16, &aVals[1]); + if (RT_FAILURE(vrc) || pszNext == NULL || *pszNext != '.') + return -1; + + vrc = RTStrToUInt8Ex(pszNext+1, &pszNext, 16, &aVals[2]); + if (RT_FAILURE(vrc) || pszNext == NULL) + return -1; + + return (aVals[0] << 8) | (aVals[1] << 3) | (aVals[2] << 0); +} +#endif + +void parseGroups(const char *pcszGroups, com::SafeArray<BSTR> *pGroups) +{ + while (pcszGroups) + { + char *pComma = RTStrStr(pcszGroups, ","); + if (pComma) + { + Bstr(pcszGroups, pComma - pcszGroups).detachTo(pGroups->appendedRaw()); + pcszGroups = pComma + 1; + } + else + { + Bstr(pcszGroups).detachTo(pGroups->appendedRaw()); + pcszGroups = NULL; + } + } +} + +#ifdef VBOX_WITH_RECORDING +int parseScreens(const char *pcszScreens, com::SafeArray<BOOL> *pScreens) +{ + if (!RTStrICmp(pcszScreens, "all")) + { + for (uint32_t i = 0; i < pScreens->size(); i++) + (*pScreens)[i] = TRUE; + return VINF_SUCCESS; + } + if (!RTStrICmp(pcszScreens, "none")) + { + for (uint32_t i = 0; i < pScreens->size(); i++) + (*pScreens)[i] = FALSE; + return VINF_SUCCESS; + } + while (pcszScreens && *pcszScreens) + { + char *pszNext; + uint32_t iScreen; + int vrc = RTStrToUInt32Ex(pcszScreens, &pszNext, 0, &iScreen); + if (RT_FAILURE(vrc)) + return VERR_PARSE_ERROR; + if (iScreen >= pScreens->size()) + return VERR_PARSE_ERROR; + if (pszNext && *pszNext) + { + pszNext = RTStrStripL(pszNext); + if (*pszNext != ',') + return VERR_PARSE_ERROR; + pszNext++; + } + (*pScreens)[iScreen] = true; + pcszScreens = pszNext; + } + return VINF_SUCCESS; +} +#endif + +static int parseNum(uint32_t uIndex, unsigned cMaxIndex, const char *pszName) +{ + if ( uIndex >= 1 + && uIndex <= cMaxIndex) + return uIndex; + errorArgument(ModifyVM::tr("Invalid %s number %u"), pszName, uIndex); + return 0; +} + +VMProcPriority_T nameToVMProcPriority(const char *pszName) +{ + if (!RTStrICmp(pszName, "default")) + return VMProcPriority_Default; + if (!RTStrICmp(pszName, "flat")) + return VMProcPriority_Flat; + if (!RTStrICmp(pszName, "low")) + return VMProcPriority_Low; + if (!RTStrICmp(pszName, "normal")) + return VMProcPriority_Normal; + if (!RTStrICmp(pszName, "high")) + return VMProcPriority_High; + + return VMProcPriority_Invalid; +} + +RTEXITCODE handleModifyVM(HandlerArg *a) +{ + int c; + HRESULT hrc; + Bstr name; + + /* VM ID + at least one parameter. Parameter arguments are checked + * individually. */ + if (a->argc < 2) + return errorSyntax(ModifyVM::tr("Not enough parameters")); + + /* try to find the given sessionMachine */ + ComPtr<IMachine> machine; + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + + + /* Get the number of network adapters */ + ULONG NetworkAdapterCount = getMaxNics(a->virtualBox, machine); + + /* open a session for the VM */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE); + + /* get the mutable session sessionMachine */ + ComPtr<IMachine> sessionMachine; + CHECK_ERROR_RET(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IBIOSSettings> biosSettings; + sessionMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); + + ComPtr<IGraphicsAdapter> pGraphicsAdapter; + sessionMachine->COMGETTER(GraphicsAdapter)(pGraphicsAdapter.asOutParam()); + + RTGETOPTSTATE GetOptState; + RTGetOptInit(&GetOptState, a->argc, a->argv, g_aModifyVMOptions, + RT_ELEMENTS(g_aModifyVMOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + + RTGETOPTUNION ValueUnion; + while ( SUCCEEDED (hrc) + && (c = RTGetOpt(&GetOptState, &ValueUnion))) + { + switch (c) + { + case MODIFYVM_NAME: + { + CHECK_ERROR(sessionMachine, COMSETTER(Name)(Bstr(ValueUnion.psz).raw())); + break; + } + case MODIFYVM_GROUPS: + { + com::SafeArray<BSTR> groups; + parseGroups(ValueUnion.psz, &groups); + CHECK_ERROR(sessionMachine, COMSETTER(Groups)(ComSafeArrayAsInParam(groups))); + break; + } + case MODIFYVM_DESCRIPTION: + { + CHECK_ERROR(sessionMachine, COMSETTER(Description)(Bstr(ValueUnion.psz).raw())); + break; + } + case MODIFYVM_OSTYPE: + { + CHECK_ERROR(sessionMachine, COMSETTER(OSTypeId)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_ICONFILE: + { + RTFILE iconFile; + int vrc = RTFileOpen(&iconFile, ValueUnion.psz, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); + if (RT_FAILURE(vrc)) + { + RTMsgError(ModifyVM::tr("Cannot open file \"%s\": %Rrc"), ValueUnion.psz, vrc); + hrc = E_FAIL; + break; + } + uint64_t cbSize; + vrc = RTFileQuerySize(iconFile, &cbSize); + if (RT_FAILURE(vrc)) + { + RTMsgError(ModifyVM::tr("Cannot get size of file \"%s\": %Rrc"), ValueUnion.psz, vrc); + hrc = E_FAIL; + break; + } + if (cbSize > _256K) + { + RTMsgError(ModifyVM::tr("File \"%s\" is bigger than 256KByte"), ValueUnion.psz); + hrc = E_FAIL; + break; + } + SafeArray<BYTE> icon((size_t)cbSize); + hrc = RTFileRead(iconFile, icon.raw(), (size_t)cbSize, NULL); + if (RT_FAILURE(vrc)) + { + RTMsgError(ModifyVM::tr("Cannot read contents of file \"%s\": %Rrc"), ValueUnion.psz, vrc); + hrc = E_FAIL; + break; + } + RTFileClose(iconFile); + CHECK_ERROR(sessionMachine, COMSETTER(Icon)(ComSafeArrayAsInParam(icon))); + break; + } + + case MODIFYVM_MEMORY: + { + CHECK_ERROR(sessionMachine, COMSETTER(MemorySize)(ValueUnion.u32)); + break; + } + + case MODIFYVM_PAGEFUSION: + { + CHECK_ERROR(sessionMachine, COMSETTER(PageFusionEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_VRAM: + { + CHECK_ERROR(pGraphicsAdapter, COMSETTER(VRAMSize)(ValueUnion.u32)); + break; + } + + case MODIFYVM_FIRMWARE: + { + if (!RTStrICmp(ValueUnion.psz, "efi")) + { + CHECK_ERROR(sessionMachine, COMSETTER(FirmwareType)(FirmwareType_EFI)); + } + else if (!RTStrICmp(ValueUnion.psz, "efi32")) + { + CHECK_ERROR(sessionMachine, COMSETTER(FirmwareType)(FirmwareType_EFI32)); + } + else if (!RTStrICmp(ValueUnion.psz, "efi64")) + { + CHECK_ERROR(sessionMachine, COMSETTER(FirmwareType)(FirmwareType_EFI64)); + } + else if (!RTStrICmp(ValueUnion.psz, "efidual")) + { + CHECK_ERROR(sessionMachine, COMSETTER(FirmwareType)(FirmwareType_EFIDUAL)); + } + else if (!RTStrICmp(ValueUnion.psz, "bios")) + { + CHECK_ERROR(sessionMachine, COMSETTER(FirmwareType)(FirmwareType_BIOS)); + } + else + { + errorArgument(ModifyVM::tr("Invalid --firmware argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_ACPI: + { + CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_IOAPIC: + { + CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_PAE: + { + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_PAE, ValueUnion.f)); + break; + } + + case MODIFYVM_LONGMODE: + { + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_LongMode, ValueUnion.f)); + break; + } + + case MODIFYVM_CPUID_PORTABILITY: + { + CHECK_ERROR(sessionMachine, COMSETTER(CPUIDPortabilityLevel)(ValueUnion.u32)); + break; + } + + case MODIFYVM_TFRESET: + { + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_TripleFaultReset, ValueUnion.f)); + break; + } + + case MODIFYVM_APIC: + { + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_APIC, ValueUnion.f)); + break; + } + + case MODIFYVM_X2APIC: + { + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_X2APIC, ValueUnion.f)); + break; + } + + case MODIFYVM_PARAVIRTPROVIDER: + { + if ( !RTStrICmp(ValueUnion.psz, "none") + || !RTStrICmp(ValueUnion.psz, "disabled")) + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtProvider)(ParavirtProvider_None)); + else if (!RTStrICmp(ValueUnion.psz, "default")) + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtProvider)(ParavirtProvider_Default)); + else if (!RTStrICmp(ValueUnion.psz, "legacy")) + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtProvider)(ParavirtProvider_Legacy)); + else if (!RTStrICmp(ValueUnion.psz, "minimal")) + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtProvider)(ParavirtProvider_Minimal)); + else if (!RTStrICmp(ValueUnion.psz, "hyperv")) + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtProvider)(ParavirtProvider_HyperV)); + else if (!RTStrICmp(ValueUnion.psz, "kvm")) + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtProvider)(ParavirtProvider_KVM)); + else + { + errorArgument(ModifyVM::tr("Invalid --paravirtprovider argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_PARAVIRTDEBUG: + { + CHECK_ERROR(sessionMachine, COMSETTER(ParavirtDebug)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_HWVIRTEX: + { + CHECK_ERROR(sessionMachine, SetHWVirtExProperty(HWVirtExPropertyType_Enabled, ValueUnion.f)); + break; + } + + case MODIFYVM_SETCPUID: + { + uint32_t const idx = c == MODIFYVM_SETCPUID ? ValueUnion.PairU32.uFirst : ValueUnion.u32; + uint32_t const idxSub = c == MODIFYVM_SETCPUID ? ValueUnion.PairU32.uSecond : UINT32_MAX; + uint32_t aValue[4]; + for (unsigned i = 0; i < 4; i++) + { + int vrc = RTGetOptFetchValue(&GetOptState, &ValueUnion, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX); + if (RT_FAILURE(vrc)) + return errorSyntax(ModifyVM::tr("Missing or invalid argument to '%s'"), + GetOptState.pDef->pszLong); + aValue[i] = ValueUnion.u32; + } + CHECK_ERROR(sessionMachine, SetCPUIDLeaf(idx, idxSub, aValue[0], aValue[1], aValue[2], aValue[3])); + break; + } + + case MODIFYVM_DELCPUID: + CHECK_ERROR(sessionMachine, RemoveCPUIDLeaf(ValueUnion.PairU32.uFirst, ValueUnion.PairU32.uSecond)); + break; + + case MODIFYVM_DELCPUID_OLD: + CHECK_ERROR(sessionMachine, RemoveCPUIDLeaf(ValueUnion.u32, UINT32_MAX)); + break; + + case MODIFYVM_DELALLCPUID: + { + CHECK_ERROR(sessionMachine, RemoveAllCPUIDLeaves()); + break; + } + + case MODIFYVM_NESTEDPAGING: + { + CHECK_ERROR(sessionMachine, SetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, ValueUnion.f)); + break; + } + + case MODIFYVM_LARGEPAGES: + { + CHECK_ERROR(sessionMachine, SetHWVirtExProperty(HWVirtExPropertyType_LargePages, ValueUnion.f)); + break; + } + + case MODIFYVM_VTXVPID: + { + CHECK_ERROR(sessionMachine, SetHWVirtExProperty(HWVirtExPropertyType_VPID, ValueUnion.f)); + break; + } + + case MODIFYVM_VTXUX: + { + CHECK_ERROR(sessionMachine, SetHWVirtExProperty(HWVirtExPropertyType_UnrestrictedExecution, ValueUnion.f)); + break; + } + + case MODIFYVM_VIRT_VMSAVE_VMLOAD: + CHECK_ERROR(sessionMachine, SetHWVirtExProperty(HWVirtExPropertyType_VirtVmsaveVmload, ValueUnion.f)); + break; + + case MODIFYVM_IBPB_ON_VM_EXIT: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_IBPBOnVMExit, ValueUnion.f)); + break; + + case MODIFYVM_IBPB_ON_VM_ENTRY: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_IBPBOnVMEntry, ValueUnion.f)); + break; + + case MODIFYVM_SPEC_CTRL: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_SpecCtrl, ValueUnion.f)); + break; + + case MODIFYVM_L1D_FLUSH_ON_SCHED: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_L1DFlushOnEMTScheduling, ValueUnion.f)); + break; + + case MODIFYVM_L1D_FLUSH_ON_VM_ENTRY: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_L1DFlushOnVMEntry, ValueUnion.f)); + break; + + case MODIFYVM_MDS_CLEAR_ON_SCHED: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_MDSClearOnEMTScheduling, ValueUnion.f)); + break; + + case MODIFYVM_MDS_CLEAR_ON_VM_ENTRY: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_MDSClearOnVMEntry, ValueUnion.f)); + break; + + case MODIFYVM_NESTED_HW_VIRT: + CHECK_ERROR(sessionMachine, SetCPUProperty(CPUPropertyType_HWVirt, ValueUnion.f)); + break; + + case MODIFYVM_CPUS: + { + CHECK_ERROR(sessionMachine, COMSETTER(CPUCount)(ValueUnion.u32)); + break; + } + + case MODIFYVM_RTCUSEUTC: + { + CHECK_ERROR(sessionMachine, COMSETTER(RTCUseUTC)(ValueUnion.f)); + break; + } + + case MODIFYVM_CPUHOTPLUG: + { + CHECK_ERROR(sessionMachine, COMSETTER(CPUHotPlugEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_CPU_PROFILE: + { + CHECK_ERROR(sessionMachine, COMSETTER(CPUProfile)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_PLUGCPU: + { + CHECK_ERROR(sessionMachine, HotPlugCPU(ValueUnion.u32)); + break; + } + + case MODIFYVM_UNPLUGCPU: + { + CHECK_ERROR(sessionMachine, HotUnplugCPU(ValueUnion.u32)); + break; + } + + case MODIFYVM_CPU_EXECTUION_CAP: + { + CHECK_ERROR(sessionMachine, COMSETTER(CPUExecutionCap)(ValueUnion.u32)); + break; + } + + case MODIFYVM_GRAPHICSCONTROLLER: + { + if ( !RTStrICmp(ValueUnion.psz, "none") + || !RTStrICmp(ValueUnion.psz, "disabled")) + CHECK_ERROR(pGraphicsAdapter, COMSETTER(GraphicsControllerType)(GraphicsControllerType_Null)); + else if ( !RTStrICmp(ValueUnion.psz, "vboxvga") + || !RTStrICmp(ValueUnion.psz, "vbox") + || !RTStrICmp(ValueUnion.psz, "vga") + || !RTStrICmp(ValueUnion.psz, "vesa")) + CHECK_ERROR(pGraphicsAdapter, COMSETTER(GraphicsControllerType)(GraphicsControllerType_VBoxVGA)); +#ifdef VBOX_WITH_VMSVGA + else if ( !RTStrICmp(ValueUnion.psz, "vmsvga") + || !RTStrICmp(ValueUnion.psz, "vmware")) + CHECK_ERROR(pGraphicsAdapter, COMSETTER(GraphicsControllerType)(GraphicsControllerType_VMSVGA)); + else if ( !RTStrICmp(ValueUnion.psz, "vboxsvga") + || !RTStrICmp(ValueUnion.psz, "svga")) + CHECK_ERROR(pGraphicsAdapter, COMSETTER(GraphicsControllerType)(GraphicsControllerType_VBoxSVGA)); +#endif + else + { + errorArgument(ModifyVM::tr("Invalid --graphicscontroller argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_MONITORCOUNT: + { + CHECK_ERROR(pGraphicsAdapter, COMSETTER(MonitorCount)(ValueUnion.u32)); + break; + } + + case MODIFYVM_ACCELERATE3D: + { + CHECK_ERROR(pGraphicsAdapter, COMSETTER(Accelerate3DEnabled)(ValueUnion.f)); + break; + } + +#ifdef VBOX_WITH_VIDEOHWACCEL + case MODIFYVM_ACCELERATE2DVIDEO: + { + CHECK_ERROR(pGraphicsAdapter, COMSETTER(Accelerate2DVideoEnabled)(ValueUnion.f)); + break; + } +#endif + + case MODIFYVM_BIOSLOGOFADEIN: + { + CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(ValueUnion.f)); + break; + } + + case MODIFYVM_BIOSLOGOFADEOUT: + { + CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(ValueUnion.f)); + break; + } + + case MODIFYVM_BIOSLOGODISPLAYTIME: + { + CHECK_ERROR(biosSettings, COMSETTER(LogoDisplayTime)(ValueUnion.u32)); + break; + } + + case MODIFYVM_BIOSLOGOIMAGEPATH: + { + CHECK_ERROR(biosSettings, COMSETTER(LogoImagePath)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_BIOSBOOTMENU: + { + if (!RTStrICmp(ValueUnion.psz, "disabled")) + { + CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_Disabled)); + } + else if (!RTStrICmp(ValueUnion.psz, "menuonly")) + { + CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MenuOnly)); + } + else if (!RTStrICmp(ValueUnion.psz, "messageandmenu")) + { + CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MessageAndMenu)); + } + else + { + errorArgument(ModifyVM::tr("Invalid --biosbootmenu argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_BIOSAPIC: + { + if (!RTStrICmp(ValueUnion.psz, "disabled")) + { + CHECK_ERROR(biosSettings, COMSETTER(APICMode)(APICMode_Disabled)); + } + else if ( !RTStrICmp(ValueUnion.psz, "apic") + || !RTStrICmp(ValueUnion.psz, "lapic") + || !RTStrICmp(ValueUnion.psz, "xapic")) + { + CHECK_ERROR(biosSettings, COMSETTER(APICMode)(APICMode_APIC)); + } + else if (!RTStrICmp(ValueUnion.psz, "x2apic")) + { + CHECK_ERROR(biosSettings, COMSETTER(APICMode)(APICMode_X2APIC)); + } + else + { + errorArgument(ModifyVM::tr("Invalid --biosapic argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_BIOSSYSTEMTIMEOFFSET: + { + CHECK_ERROR(biosSettings, COMSETTER(TimeOffset)(ValueUnion.i64)); + break; + } + + case MODIFYVM_BIOSPXEDEBUG: + { + CHECK_ERROR(biosSettings, COMSETTER(PXEDebugEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_SYSTEMUUIDLE: + { + CHECK_ERROR(biosSettings, COMSETTER(SMBIOSUuidLittleEndian)(ValueUnion.f)); + break; + } + + case MODIFYVM_BOOT: + { + if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(sessionMachine, SetBootOrder(GetOptState.uIndex, DeviceType_Null)); + } + else if (!RTStrICmp(ValueUnion.psz, "floppy")) + { + CHECK_ERROR(sessionMachine, SetBootOrder(GetOptState.uIndex, DeviceType_Floppy)); + } + else if (!RTStrICmp(ValueUnion.psz, "dvd")) + { + CHECK_ERROR(sessionMachine, SetBootOrder(GetOptState.uIndex, DeviceType_DVD)); + } + else if (!RTStrICmp(ValueUnion.psz, "disk")) + { + CHECK_ERROR(sessionMachine, SetBootOrder(GetOptState.uIndex, DeviceType_HardDisk)); + } + else if (!RTStrICmp(ValueUnion.psz, "net")) + { + CHECK_ERROR(sessionMachine, SetBootOrder(GetOptState.uIndex, DeviceType_Network)); + } + else + return errorArgument(ModifyVM::tr("Invalid boot device '%s'"), ValueUnion.psz); + break; + } + + case MODIFYVM_HDA: // deprecated + case MODIFYVM_HDB: // deprecated + case MODIFYVM_HDD: // deprecated + case MODIFYVM_SATAPORT: // deprecated + { + uint32_t u1 = 0, u2 = 0; + Bstr bstrController = L"IDE Controller"; + + switch (c) + { + case MODIFYVM_HDA: // deprecated + u1 = 0; + break; + + case MODIFYVM_HDB: // deprecated + u1 = 0; + u2 = 1; + break; + + case MODIFYVM_HDD: // deprecated + u1 = 1; + u2 = 1; + break; + + case MODIFYVM_SATAPORT: // deprecated + u1 = GetOptState.uIndex; + bstrController = L"SATA"; + break; + } + + if (!RTStrICmp(ValueUnion.psz, "none")) + { + sessionMachine->DetachDevice(bstrController.raw(), u1, u2); + } + else + { + ComPtr<IMedium> hardDisk; + hrc = openMedium(a, ValueUnion.psz, DeviceType_HardDisk, + AccessMode_ReadWrite, hardDisk, + false /* fForceNewUuidOnOpen */, + false /* fSilent */); + if (FAILED(hrc)) + break; + if (hardDisk) + { + CHECK_ERROR(sessionMachine, AttachDevice(bstrController.raw(), + u1, u2, + DeviceType_HardDisk, + hardDisk)); + } + else + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_IDECONTROLLER: // deprecated + { + ComPtr<IStorageController> storageController; + CHECK_ERROR(sessionMachine, GetStorageControllerByName(Bstr("IDE Controller").raw(), + storageController.asOutParam())); + + if (!RTStrICmp(ValueUnion.psz, "PIIX3")) + { + CHECK_ERROR(storageController, COMSETTER(ControllerType)(StorageControllerType_PIIX3)); + } + else if (!RTStrICmp(ValueUnion.psz, "PIIX4")) + { + CHECK_ERROR(storageController, COMSETTER(ControllerType)(StorageControllerType_PIIX4)); + } + else if (!RTStrICmp(ValueUnion.psz, "ICH6")) + { + CHECK_ERROR(storageController, COMSETTER(ControllerType)(StorageControllerType_ICH6)); + } + else + { + errorArgument(ModifyVM::tr("Invalid --idecontroller argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_SATAPORTCOUNT: // deprecated + { + ComPtr<IStorageController> SataCtl; + CHECK_ERROR(sessionMachine, GetStorageControllerByName(Bstr("SATA").raw(), + SataCtl.asOutParam())); + + if (SUCCEEDED(hrc) && ValueUnion.u32 > 0) + CHECK_ERROR(SataCtl, COMSETTER(PortCount)(ValueUnion.u32)); + break; + } + + case MODIFYVM_SATA: // deprecated + { + if (!RTStrICmp(ValueUnion.psz, "on") || !RTStrICmp(ValueUnion.psz, "enable")) + { + ComPtr<IStorageController> ctl; + CHECK_ERROR(sessionMachine, AddStorageController(Bstr("SATA").raw(), + StorageBus_SATA, + ctl.asOutParam())); + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci)); + } + else if (!RTStrICmp(ValueUnion.psz, "off") || !RTStrICmp(ValueUnion.psz, "disable")) + CHECK_ERROR(sessionMachine, RemoveStorageController(Bstr("SATA").raw())); + else + return errorArgument(ModifyVM::tr("Invalid --usb argument '%s'"), ValueUnion.psz); + break; + } + + case MODIFYVM_SCSIPORT: // deprecated + { + if (!RTStrICmp(ValueUnion.psz, "none")) + { + hrc = sessionMachine->DetachDevice(Bstr("LsiLogic").raw(), + GetOptState.uIndex, 0); + if (FAILED(hrc)) + CHECK_ERROR(sessionMachine, DetachDevice(Bstr("BusLogic").raw(), + GetOptState.uIndex, 0)); + } + else + { + ComPtr<IMedium> hardDisk; + hrc = openMedium(a, ValueUnion.psz, DeviceType_HardDisk, + AccessMode_ReadWrite, hardDisk, + false /* fForceNewUuidOnOpen */, + false /* fSilent */); + if (FAILED(hrc)) + break; + if (hardDisk) + { + hrc = sessionMachine->AttachDevice(Bstr("LsiLogic").raw(), + GetOptState.uIndex, 0, + DeviceType_HardDisk, + hardDisk); + if (FAILED(hrc)) + CHECK_ERROR(sessionMachine, + AttachDevice(Bstr("BusLogic").raw(), + GetOptState.uIndex, 0, + DeviceType_HardDisk, + hardDisk)); + } + else + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_SCSITYPE: // deprecated + { + ComPtr<IStorageController> ctl; + + if (!RTStrICmp(ValueUnion.psz, "LsiLogic")) + { + hrc = sessionMachine->RemoveStorageController(Bstr("BusLogic").raw()); + if (FAILED(hrc)) + CHECK_ERROR(sessionMachine, RemoveStorageController(Bstr("LsiLogic").raw())); + + CHECK_ERROR(sessionMachine, + AddStorageController(Bstr("LsiLogic").raw(), + StorageBus_SCSI, + ctl.asOutParam())); + + if (SUCCEEDED(hrc)) + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic)); + } + else if (!RTStrICmp(ValueUnion.psz, "BusLogic")) + { + hrc = sessionMachine->RemoveStorageController(Bstr("LsiLogic").raw()); + if (FAILED(hrc)) + CHECK_ERROR(sessionMachine, RemoveStorageController(Bstr("BusLogic").raw())); + + CHECK_ERROR(sessionMachine, + AddStorageController(Bstr("BusLogic").raw(), + StorageBus_SCSI, + ctl.asOutParam())); + + if (SUCCEEDED(hrc)) + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic)); + } + else + return errorArgument(ModifyVM::tr("Invalid --scsitype argument '%s'"), ValueUnion.psz); + break; + } + + case MODIFYVM_SCSI: // deprecated + { + if (!RTStrICmp(ValueUnion.psz, "on") || !RTStrICmp(ValueUnion.psz, "enable")) + { + ComPtr<IStorageController> ctl; + + CHECK_ERROR(sessionMachine, AddStorageController(Bstr("BusLogic").raw(), + StorageBus_SCSI, + ctl.asOutParam())); + if (SUCCEEDED(hrc)) + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic)); + } + else if (!RTStrICmp(ValueUnion.psz, "off") || !RTStrICmp(ValueUnion.psz, "disable")) + { + hrc = sessionMachine->RemoveStorageController(Bstr("BusLogic").raw()); + if (FAILED(hrc)) + CHECK_ERROR(sessionMachine, RemoveStorageController(Bstr("LsiLogic").raw())); + } + break; + } + + case MODIFYVM_DVDPASSTHROUGH: // deprecated + { + CHECK_ERROR(sessionMachine, PassthroughDevice(Bstr("IDE Controller").raw(), + 1, 0, + !RTStrICmp(ValueUnion.psz, "on"))); + break; + } + + case MODIFYVM_DVD: // deprecated + { + ComPtr<IMedium> dvdMedium; + + /* unmount? */ + if (!RTStrICmp(ValueUnion.psz, "none")) + { + /* nothing to do, NULL object will cause unmount */ + } + /* host drive? */ + else if (!RTStrNICmp(ValueUnion.psz, RT_STR_TUPLE("host:"))) + { + ComPtr<IHost> host; + CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam())); + hrc = host->FindHostDVDDrive(Bstr(ValueUnion.psz + 5).raw(), + dvdMedium.asOutParam()); + if (!dvdMedium) + { + /* 2nd try: try with the real name, important on Linux+libhal */ + char szPathReal[RTPATH_MAX]; + if (RT_FAILURE(RTPathReal(ValueUnion.psz + 5, szPathReal, sizeof(szPathReal)))) + { + errorArgument(ModifyVM::tr("Invalid host DVD drive name \"%s\""), ValueUnion.psz + 5); + hrc = E_FAIL; + break; + } + hrc = host->FindHostDVDDrive(Bstr(szPathReal).raw(), + dvdMedium.asOutParam()); + if (!dvdMedium) + { + errorArgument(ModifyVM::tr("Invalid host DVD drive name \"%s\""), ValueUnion.psz + 5); + hrc = E_FAIL; + break; + } + } + } + else + { + hrc = openMedium(a, ValueUnion.psz, DeviceType_DVD, + AccessMode_ReadOnly, dvdMedium, + false /* fForceNewUuidOnOpen */, + false /* fSilent */); + if (FAILED(hrc)) + break; + if (!dvdMedium) + { + hrc = E_FAIL; + break; + } + } + + CHECK_ERROR(sessionMachine, MountMedium(Bstr("IDE Controller").raw(), + 1, 0, + dvdMedium, + FALSE /* aForce */)); + break; + } + + case MODIFYVM_FLOPPY: // deprecated + { + ComPtr<IMedium> floppyMedium; + ComPtr<IMediumAttachment> floppyAttachment; + sessionMachine->GetMediumAttachment(Bstr("Floppy Controller").raw(), + 0, 0, floppyAttachment.asOutParam()); + + /* disable? */ + if (!RTStrICmp(ValueUnion.psz, "disabled")) + { + /* disable the controller */ + if (floppyAttachment) + CHECK_ERROR(sessionMachine, DetachDevice(Bstr("Floppy Controller").raw(), + 0, 0)); + } + else + { + /* enable the controller */ + if (!floppyAttachment) + CHECK_ERROR(sessionMachine, AttachDeviceWithoutMedium(Bstr("Floppy Controller").raw(), + 0, 0, + DeviceType_Floppy)); + + /* unmount? */ + if ( !RTStrICmp(ValueUnion.psz, "none") + || !RTStrICmp(ValueUnion.psz, "empty")) // deprecated + { + /* nothing to do, NULL object will cause unmount */ + } + /* host drive? */ + else if (!RTStrNICmp(ValueUnion.psz, RT_STR_TUPLE("host:"))) + { + ComPtr<IHost> host; + CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam())); + hrc = host->FindHostFloppyDrive(Bstr(ValueUnion.psz + 5).raw(), + floppyMedium.asOutParam()); + if (!floppyMedium) + { + errorArgument(ModifyVM::tr("Invalid host floppy drive name \"%s\""), ValueUnion.psz + 5); + hrc = E_FAIL; + break; + } + } + else + { + hrc = openMedium(a, ValueUnion.psz, DeviceType_Floppy, + AccessMode_ReadWrite, floppyMedium, + false /* fForceNewUuidOnOpen */, + false /* fSilent */); + if (FAILED(hrc)) + break; + if (!floppyMedium) + { + hrc = E_FAIL; + break; + } + } + CHECK_ERROR(sessionMachine, MountMedium(Bstr("Floppy Controller").raw(), + 0, 0, + floppyMedium, + FALSE /* aForce */)); + } + break; + } + + case MODIFYVM_NICTRACEFILE: + { + + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(TraceFile)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_NICTRACE: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(TraceEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_NICPROPERTY: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + if (nic) + { + /* Parse 'name=value' */ + char *pszProperty = RTStrDup(ValueUnion.psz); + if (pszProperty) + { + char *pDelimiter = strchr(pszProperty, '='); + if (pDelimiter) + { + *pDelimiter = '\0'; + + Bstr bstrName = pszProperty; + Bstr bstrValue = &pDelimiter[1]; + CHECK_ERROR(nic, SetProperty(bstrName.raw(), bstrValue.raw())); + } + else + { + errorArgument(ModifyVM::tr("Invalid --nicproperty%d argument '%s'"), GetOptState.uIndex, ValueUnion.psz); + hrc = E_FAIL; + } + RTStrFree(pszProperty); + } + else + { + RTStrmPrintf(g_pStdErr, ModifyVM::tr("Error: Failed to allocate memory for --nicproperty%d '%s'\n"), + GetOptState.uIndex, ValueUnion.psz); + hrc = E_FAIL; + } + } + break; + } + case MODIFYVM_NICTYPE: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + if (!RTStrICmp(ValueUnion.psz, "Am79C970A")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_Am79C970A)); + } + else if (!RTStrICmp(ValueUnion.psz, "Am79C973")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_Am79C973)); + } + else if (!RTStrICmp(ValueUnion.psz, "Am79C960")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_Am79C960)); + } +#ifdef VBOX_WITH_E1000 + else if (!RTStrICmp(ValueUnion.psz, "82540EM")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_I82540EM)); + } + else if (!RTStrICmp(ValueUnion.psz, "82543GC")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_I82543GC)); + } + else if (!RTStrICmp(ValueUnion.psz, "82545EM")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_I82545EM)); + } +#endif +#ifdef VBOX_WITH_VIRTIO + else if (!RTStrICmp(ValueUnion.psz, "virtio")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_Virtio)); + } +#endif /* VBOX_WITH_VIRTIO */ + else if (!RTStrICmp(ValueUnion.psz, "NE1000")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_NE1000)); + } + else if (!RTStrICmp(ValueUnion.psz, "NE2000")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_NE2000)); + } + else if (!RTStrICmp(ValueUnion.psz, "WD8003")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_WD8003)); + } + else if (!RTStrICmp(ValueUnion.psz, "WD8013")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_WD8013)); + } + else if (!RTStrICmp(ValueUnion.psz, "3C503")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_ELNK2)); + } + else if (!RTStrICmp(ValueUnion.psz, "3C501")) + { + CHECK_ERROR(nic, COMSETTER(AdapterType)(NetworkAdapterType_ELNK1)); + } + else + { + errorArgument(ModifyVM::tr("Invalid NIC type '%s' specified for NIC %u"), + ValueUnion.psz, GetOptState.uIndex); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_NICSPEED: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(LineSpeed)(ValueUnion.u32)); + break; + } + + case MODIFYVM_NICBOOTPRIO: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* Somewhat arbitrary limitation - we can pass a list of up to 4 PCI devices + * to the PXE ROM, hence only boot priorities 1-4 are allowed (in addition to + * 0 for the default lowest priority). + */ + if (ValueUnion.u32 > 4) + { + errorArgument(ModifyVM::tr("Invalid boot priority '%u' specfied for NIC %u"), ValueUnion.u32, GetOptState.uIndex); + hrc = E_FAIL; + } + else + { + CHECK_ERROR(nic, COMSETTER(BootPriority)(ValueUnion.u32)); + } + break; + } + + case MODIFYVM_NICPROMISC: + { + NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy; + if (!RTStrICmp(ValueUnion.psz, "deny")) + enmPromiscModePolicy = NetworkAdapterPromiscModePolicy_Deny; + else if ( !RTStrICmp(ValueUnion.psz, "allow-vms") + || !RTStrICmp(ValueUnion.psz, "allow-network")) + enmPromiscModePolicy = NetworkAdapterPromiscModePolicy_AllowNetwork; + else if (!RTStrICmp(ValueUnion.psz, "allow-all")) + enmPromiscModePolicy = NetworkAdapterPromiscModePolicy_AllowAll; + else + { + errorArgument(ModifyVM::tr("Unknown promiscuous mode policy '%s'"), ValueUnion.psz); + hrc = E_INVALIDARG; + break; + } + + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(PromiscModePolicy)(enmPromiscModePolicy)); + break; + } + + case MODIFYVM_NICBWGROUP: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + if (!RTStrICmp(ValueUnion.psz, "none")) + { + /* Just remove the bandwidth group. */ + CHECK_ERROR(nic, COMSETTER(BandwidthGroup)(NULL)); + } + else + { + ComPtr<IBandwidthControl> bwCtrl; + ComPtr<IBandwidthGroup> bwGroup; + + CHECK_ERROR(sessionMachine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam())); + + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(bwCtrl, GetBandwidthGroup(Bstr(ValueUnion.psz).raw(), bwGroup.asOutParam())); + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(nic, COMSETTER(BandwidthGroup)(bwGroup)); + } + } + } + break; + } + + case MODIFYVM_NIC: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* + * Check if the NIC is already enabled. Do not try to + * enable it if it already is. That makes a + * difference for saved VMs for which you can change + * the NIC attachment, but can't change the NIC + * enabled status (yes, the setter also should not + * freak out about a no-op request). + */ + BOOL fEnabled;; + CHECK_ERROR(nic, COMGETTER(Enabled)(&fEnabled)); + + if (!RTStrICmp(ValueUnion.psz, "none")) + { + if (RT_BOOL(fEnabled)) + CHECK_ERROR(nic, COMSETTER(Enabled)(FALSE)); + } + else if (!RTStrICmp(ValueUnion.psz, "null")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_Null)); + } + else if (!RTStrICmp(ValueUnion.psz, "nat")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_NAT)); + } + else if ( !RTStrICmp(ValueUnion.psz, "bridged") + || !RTStrICmp(ValueUnion.psz, "hostif")) /* backward compatibility */ + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_Bridged)); + } + else if (!RTStrICmp(ValueUnion.psz, "intnet")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_Internal)); + } + else if (!RTStrICmp(ValueUnion.psz, "hostonly")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_HostOnly)); + } +#ifdef VBOX_WITH_VMNET + else if (!RTStrICmp(ValueUnion.psz, "hostonlynet")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_HostOnlyNetwork)); + } +#endif /* VBOX_WITH_VMNET */ + else if (!RTStrICmp(ValueUnion.psz, "generic")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_Generic)); + } + else if (!RTStrICmp(ValueUnion.psz, "natnetwork")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_NATNetwork)); + } +#ifdef VBOX_WITH_CLOUD_NET + else if (!RTStrICmp(ValueUnion.psz, "cloud")) + { + if (!fEnabled) + CHECK_ERROR(nic, COMSETTER(Enabled)(TRUE)); + CHECK_ERROR(nic, COMSETTER(AttachmentType)(NetworkAttachmentType_Cloud)); + } +#endif /* VBOX_WITH_CLOUD_NET */ + else + { + errorArgument(ModifyVM::tr("Invalid type '%s' specfied for NIC %u"), ValueUnion.psz, GetOptState.uIndex); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_CABLECONNECTED: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(CableConnected)(ValueUnion.f)); + break; + } + + case MODIFYVM_BRIDGEADAPTER: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* remove it? */ + if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(nic, COMSETTER(BridgedInterface)(Bstr().raw())); + } + else + { + CHECK_ERROR(nic, COMSETTER(BridgedInterface)(Bstr(ValueUnion.psz).raw())); + verifyHostNetworkInterfaceName(a->virtualBox, ValueUnion.psz, + HostNetworkInterfaceType_Bridged); + } + break; + } + +#ifdef VBOX_WITH_CLOUD_NET + case MODIFYVM_CLOUDNET: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* remove it? */ + if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(nic, COMSETTER(CloudNetwork)(Bstr().raw())); + } + else + { + CHECK_ERROR(nic, COMSETTER(CloudNetwork)(Bstr(ValueUnion.psz).raw())); + } + break; + } +#endif /* VBOX_WITH_CLOUD_NET */ + + case MODIFYVM_HOSTONLYADAPTER: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* remove it? */ + if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(nic, COMSETTER(HostOnlyInterface)(Bstr().raw())); + } + else + { + CHECK_ERROR(nic, COMSETTER(HostOnlyInterface)(Bstr(ValueUnion.psz).raw())); + verifyHostNetworkInterfaceName(a->virtualBox, ValueUnion.psz, + HostNetworkInterfaceType_HostOnly); + } + break; + } + +#ifdef VBOX_WITH_VMNET + case MODIFYVM_HOSTONLYNET: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* remove it? */ + if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(nic, COMSETTER(HostOnlyNetwork)(Bstr().raw())); + } + else + { + CHECK_ERROR(nic, COMSETTER(HostOnlyNetwork)(Bstr(ValueUnion.psz).raw())); + } + break; + } +#endif /* VBOX_WITH_VMNET */ + + case MODIFYVM_INTNET: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* remove it? */ + if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(nic, COMSETTER(InternalNetwork)(Bstr().raw())); + } + else + { + CHECK_ERROR(nic, COMSETTER(InternalNetwork)(Bstr(ValueUnion.psz).raw())); + } + break; + } + + case MODIFYVM_GENERICDRV: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(GenericDriver)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_NATNETWORKNAME: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMSETTER(NATNetwork)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_NATNET: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + const char *psz = ValueUnion.psz; + if (!RTStrICmp("default", psz)) + psz = ""; + + CHECK_ERROR(engine, COMSETTER(Network)(Bstr(psz).raw())); + break; + } + + case MODIFYVM_NATBINDIP: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(HostIP)(Bstr(ValueUnion.psz).raw())); + break; + } + +#define ITERATE_TO_NEXT_TERM(ch) \ + do { \ + while (*ch != ',') \ + { \ + if (*ch == 0) \ + { \ + return errorSyntax(ModifyVM::tr("Missing or invalid argument to '%s'"), \ + GetOptState.pDef->pszLong); \ + } \ + ch++; \ + } \ + *ch = '\0'; \ + ch++; \ + } while(0) + + case MODIFYVM_NATSETTINGS: + { + ComPtr<INetworkAdapter> nic; + ComPtr<INATEngine> engine; + char *strMtu; + char *strSockSnd; + char *strSockRcv; + char *strTcpSnd; + char *strTcpRcv; + char *strRaw = RTStrDup(ValueUnion.psz); + char *ch = strRaw; + strMtu = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strSockSnd = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strSockRcv = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strTcpSnd = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strTcpRcv = RTStrStrip(ch); + + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + CHECK_ERROR(engine, SetNetworkSettings(RTStrToUInt32(strMtu), RTStrToUInt32(strSockSnd), RTStrToUInt32(strSockRcv), + RTStrToUInt32(strTcpSnd), RTStrToUInt32(strTcpRcv))); + break; + } + + + case MODIFYVM_NATPF: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + /* format name:proto:hostip:hostport:guestip:guestport*/ + if (RTStrCmp(ValueUnion.psz, "delete") != 0) + { + char *strName; + char *strProto; + char *strHostIp; + char *strHostPort; + char *strGuestIp; + char *strGuestPort; + char *strRaw = RTStrDup(ValueUnion.psz); + char *ch = strRaw; + strName = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strProto = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strHostIp = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strHostPort = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strGuestIp = RTStrStrip(ch); + ITERATE_TO_NEXT_TERM(ch); + strGuestPort = RTStrStrip(ch); + NATProtocol_T proto; + if (RTStrICmp(strProto, "udp") == 0) + proto = NATProtocol_UDP; + else if (RTStrICmp(strProto, "tcp") == 0) + proto = NATProtocol_TCP; + else + { + errorArgument(ModifyVM::tr("Invalid proto '%s' specfied for NIC %u"), ValueUnion.psz, GetOptState.uIndex); + hrc = E_FAIL; + break; + } + CHECK_ERROR(engine, AddRedirect(Bstr(strName).raw(), proto, + Bstr(strHostIp).raw(), + RTStrToUInt16(strHostPort), + Bstr(strGuestIp).raw(), + RTStrToUInt16(strGuestPort))); + } + else + { + /* delete NAT Rule operation */ + int vrc; + vrc = RTGetOptFetchValue(&GetOptState, &ValueUnion, RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorSyntax(ModifyVM::tr("Not enough parameters")); + CHECK_ERROR(engine, RemoveRedirect(Bstr(ValueUnion.psz).raw())); + } + break; + } + #undef ITERATE_TO_NEXT_TERM + case MODIFYVM_NATALIASMODE: + { + ComPtr<INetworkAdapter> nic; + ComPtr<INATEngine> engine; + uint32_t aliasMode = 0; + + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + if (RTStrCmp(ValueUnion.psz, "default") == 0) + aliasMode = 0; + else + { + char *token = (char *)ValueUnion.psz; + while (token) + { + if (RTStrNCmp(token, RT_STR_TUPLE("log")) == 0) + aliasMode |= NATAliasMode_AliasLog; + else if (RTStrNCmp(token, RT_STR_TUPLE("proxyonly")) == 0) + aliasMode |= NATAliasMode_AliasProxyOnly; + else if (RTStrNCmp(token, RT_STR_TUPLE("sameports")) == 0) + aliasMode |= NATAliasMode_AliasUseSamePorts; + token = RTStrStr(token, ","); + if (token == NULL) + break; + token++; + } + } + CHECK_ERROR(engine, COMSETTER(AliasMode)(aliasMode)); + break; + } + + case MODIFYVM_NATTFTPPREFIX: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(TFTPPrefix)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_NATTFTPFILE: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(TFTPBootFile)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_NATTFTPSERVER: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(TFTPNextServer)(Bstr(ValueUnion.psz).raw())); + break; + } + case MODIFYVM_NATDNSPASSDOMAIN: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(DNSPassDomain)(ValueUnion.f)); + break; + } + + case MODIFYVM_NATDNSPROXY: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(DNSProxy)(ValueUnion.f)); + break; + } + + case MODIFYVM_NATDNSHOSTRESOLVER: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(DNSUseHostResolver)(ValueUnion.f)); + break; + } + + case MODIFYVM_NATLOCALHOSTREACHABLE: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + ComPtr<INATEngine> engine; + CHECK_ERROR(nic, COMGETTER(NATEngine)(engine.asOutParam())); + + CHECK_ERROR(engine, COMSETTER(LocalhostReachable)(ValueUnion.f)); + break; + } + + case MODIFYVM_MACADDRESS: + { + if (!parseNum(GetOptState.uIndex, NetworkAdapterCount, "NIC")) + break; + + ComPtr<INetworkAdapter> nic; + CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(GetOptState.uIndex - 1, nic.asOutParam())); + ASSERT(nic); + + /* generate one? */ + if (!RTStrICmp(ValueUnion.psz, "auto")) + { + CHECK_ERROR(nic, COMSETTER(MACAddress)(Bstr().raw())); + } + else + { + CHECK_ERROR(nic, COMSETTER(MACAddress)(Bstr(ValueUnion.psz).raw())); + } + break; + } + + case MODIFYVM_HIDPTR: + { + bool fEnableUsb = false; + if (!RTStrICmp(ValueUnion.psz, "ps2")) + { + CHECK_ERROR(sessionMachine, COMSETTER(PointingHIDType)(PointingHIDType_PS2Mouse)); + } + else if (!RTStrICmp(ValueUnion.psz, "usb")) + { + CHECK_ERROR(sessionMachine, COMSETTER(PointingHIDType)(PointingHIDType_USBMouse)); + if (SUCCEEDED(hrc)) + fEnableUsb = true; + } + else if (!RTStrICmp(ValueUnion.psz, "usbtablet")) + { + CHECK_ERROR(sessionMachine, COMSETTER(PointingHIDType)(PointingHIDType_USBTablet)); + if (SUCCEEDED(hrc)) + fEnableUsb = true; + } + else if (!RTStrICmp(ValueUnion.psz, "usbmultitouch")) + { + CHECK_ERROR(sessionMachine, COMSETTER(PointingHIDType)(PointingHIDType_USBMultiTouch)); + if (SUCCEEDED(hrc)) + fEnableUsb = true; + } + else if (!RTStrICmp(ValueUnion.psz, "usbmtscreenpluspad")) + { + CHECK_ERROR(sessionMachine, COMSETTER(PointingHIDType)(PointingHIDType_USBMultiTouchScreenPlusPad)); + if (SUCCEEDED(hrc)) + fEnableUsb = true; + } + else if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(sessionMachine, COMSETTER(PointingHIDType)(PointingHIDType_None)); + } + else + { + errorArgument(ModifyVM::tr("Invalid type '%s' specfied for pointing device"), ValueUnion.psz); + hrc = E_FAIL; + } + if (fEnableUsb) + { + /* Make sure either the OHCI or xHCI controller is enabled. */ + ULONG cOhciCtrls = 0; + ULONG cXhciCtrls = 0; + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_OHCI, &cOhciCtrls); + if (SUCCEEDED(hrc)) { + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_XHCI, &cXhciCtrls); + if ( SUCCEEDED(hrc) + && cOhciCtrls + cXhciCtrls == 0) + { + /* If there's nothing, enable OHCI (always available). */ + ComPtr<IUSBController> UsbCtl; + CHECK_ERROR(sessionMachine, AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI, + UsbCtl.asOutParam())); + } + } + } + break; + } + + case MODIFYVM_HIDKBD: + { + bool fEnableUsb = false; + if (!RTStrICmp(ValueUnion.psz, "ps2")) + { + CHECK_ERROR(sessionMachine, COMSETTER(KeyboardHIDType)(KeyboardHIDType_PS2Keyboard)); + } + else if (!RTStrICmp(ValueUnion.psz, "usb")) + { + CHECK_ERROR(sessionMachine, COMSETTER(KeyboardHIDType)(KeyboardHIDType_USBKeyboard)); + if (SUCCEEDED(hrc)) + fEnableUsb = true; + } + else if (!RTStrICmp(ValueUnion.psz, "none")) + { + CHECK_ERROR(sessionMachine, COMSETTER(KeyboardHIDType)(KeyboardHIDType_None)); + if (SUCCEEDED(hrc)) + fEnableUsb = true; + } + else + { + errorArgument(ModifyVM::tr("Invalid type '%s' specfied for keyboard"), ValueUnion.psz); + hrc = E_FAIL; + } + if (fEnableUsb) + { + /* Make sure either the OHCI or xHCI controller is enabled. */ + ULONG cOhciCtrls = 0; + ULONG cXhciCtrls = 0; + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_OHCI, &cOhciCtrls); + if (SUCCEEDED(hrc)) { + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_XHCI, &cXhciCtrls); + if ( SUCCEEDED(hrc) + && cOhciCtrls + cXhciCtrls == 0) + { + /* If there's nothing, enable OHCI (always available). */ + ComPtr<IUSBController> UsbCtl; + CHECK_ERROR(sessionMachine, AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI, + UsbCtl.asOutParam())); + } + } + } + break; + } + + case MODIFYVM_UARTMODE: + { + ComPtr<ISerialPort> uart; + + CHECK_ERROR_BREAK(sessionMachine, GetSerialPort(GetOptState.uIndex - 1, uart.asOutParam())); + ASSERT(uart); + + if (!RTStrICmp(ValueUnion.psz, "disconnected")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_Disconnected)); + } + else if ( !RTStrICmp(ValueUnion.psz, "server") + || !RTStrICmp(ValueUnion.psz, "client") + || !RTStrICmp(ValueUnion.psz, "tcpserver") + || !RTStrICmp(ValueUnion.psz, "tcpclient") + || !RTStrICmp(ValueUnion.psz, "file")) + { + const char *pszMode = ValueUnion.psz; + + int vrc = RTGetOptFetchValue(&GetOptState, &ValueUnion, RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorSyntax(ModifyVM::tr("Missing or invalid argument to '%s'"), + GetOptState.pDef->pszLong); + + CHECK_ERROR(uart, COMSETTER(Path)(Bstr(ValueUnion.psz).raw())); + + if (!RTStrICmp(pszMode, "server")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_HostPipe)); + CHECK_ERROR(uart, COMSETTER(Server)(TRUE)); + } + else if (!RTStrICmp(pszMode, "client")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_HostPipe)); + CHECK_ERROR(uart, COMSETTER(Server)(FALSE)); + } + else if (!RTStrICmp(pszMode, "tcpserver")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_TCP)); + CHECK_ERROR(uart, COMSETTER(Server)(TRUE)); + } + else if (!RTStrICmp(pszMode, "tcpclient")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_TCP)); + CHECK_ERROR(uart, COMSETTER(Server)(FALSE)); + } + else if (!RTStrICmp(pszMode, "file")) + { + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_RawFile)); + } + } + else + { + CHECK_ERROR(uart, COMSETTER(Path)(Bstr(ValueUnion.psz).raw())); + CHECK_ERROR(uart, COMSETTER(HostMode)(PortMode_HostDevice)); + } + break; + } + + case MODIFYVM_UARTTYPE: + { + ComPtr<ISerialPort> uart; + + CHECK_ERROR_BREAK(sessionMachine, GetSerialPort(GetOptState.uIndex - 1, uart.asOutParam())); + ASSERT(uart); + + if (!RTStrICmp(ValueUnion.psz, "16450")) + { + CHECK_ERROR(uart, COMSETTER(UartType)(UartType_U16450)); + } + else if (!RTStrICmp(ValueUnion.psz, "16550A")) + { + CHECK_ERROR(uart, COMSETTER(UartType)(UartType_U16550A)); + } + else if (!RTStrICmp(ValueUnion.psz, "16750")) + { + CHECK_ERROR(uart, COMSETTER(UartType)(UartType_U16750)); + } + else + return errorSyntax(ModifyVM::tr("Invalid argument to '%s'"), + GetOptState.pDef->pszLong); + break; + } + + case MODIFYVM_UART: + { + ComPtr<ISerialPort> uart; + + CHECK_ERROR_BREAK(sessionMachine, GetSerialPort(GetOptState.uIndex - 1, uart.asOutParam())); + ASSERT(uart); + + if (!RTStrICmp(ValueUnion.psz, "off") || !RTStrICmp(ValueUnion.psz, "disable")) + CHECK_ERROR(uart, COMSETTER(Enabled)(FALSE)); + else + { + const char *pszIOBase = ValueUnion.psz; + uint32_t uVal = 0; + + int vrc = RTGetOptFetchValue(&GetOptState, &ValueUnion, RTGETOPT_REQ_UINT32) != MODIFYVM_UART; + if (RT_FAILURE(vrc)) + return errorSyntax(ModifyVM::tr("Missing or invalid argument to '%s'"), + GetOptState.pDef->pszLong); + + CHECK_ERROR(uart, COMSETTER(IRQ)(ValueUnion.u32)); + + vrc = RTStrToUInt32Ex(pszIOBase, NULL, 0, &uVal); + if (vrc != VINF_SUCCESS || uVal == 0) + return errorArgument(ModifyVM::tr("Error parsing UART I/O base '%s'"), pszIOBase); + CHECK_ERROR(uart, COMSETTER(IOBase)(uVal)); + + CHECK_ERROR(uart, COMSETTER(Enabled)(TRUE)); + } + break; + } + +#if defined(RT_OS_LINUX) || defined(RT_OS_WINDOWS) + case MODIFYVM_LPTMODE: + { + ComPtr<IParallelPort> lpt; + + CHECK_ERROR_BREAK(sessionMachine, GetParallelPort(GetOptState.uIndex - 1, lpt.asOutParam())); + ASSERT(lpt); + + CHECK_ERROR(lpt, COMSETTER(Path)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_LPT: + { + ComPtr<IParallelPort> lpt; + + CHECK_ERROR_BREAK(sessionMachine, GetParallelPort(GetOptState.uIndex - 1, lpt.asOutParam())); + ASSERT(lpt); + + if (!RTStrICmp(ValueUnion.psz, "off") || !RTStrICmp(ValueUnion.psz, "disable")) + CHECK_ERROR(lpt, COMSETTER(Enabled)(FALSE)); + else + { + const char *pszIOBase = ValueUnion.psz; + uint32_t uVal = 0; + + int vrc = RTGetOptFetchValue(&GetOptState, &ValueUnion, RTGETOPT_REQ_UINT32) != MODIFYVM_LPT; + if (RT_FAILURE(vrc)) + return errorSyntax(ModifyVM::tr("Missing or invalid argument to '%s'"), + GetOptState.pDef->pszLong); + + CHECK_ERROR(lpt, COMSETTER(IRQ)(ValueUnion.u32)); + + vrc = RTStrToUInt32Ex(pszIOBase, NULL, 0, &uVal); + if (vrc != VINF_SUCCESS || uVal == 0) + return errorArgument(ModifyVM::tr("Error parsing LPT I/O base '%s'"), pszIOBase); + CHECK_ERROR(lpt, COMSETTER(IOBase)(uVal)); + + CHECK_ERROR(lpt, COMSETTER(Enabled)(TRUE)); + } + break; + } +#endif + + case MODIFYVM_GUESTMEMORYBALLOON: + { + CHECK_ERROR(sessionMachine, COMSETTER(MemoryBalloonSize)(ValueUnion.u32)); + break; + } + + case MODIFYVM_AUDIOCONTROLLER: + { + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> audioAdapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(audioAdapter.asOutParam())); + ASSERT(audioAdapter); + + if (!RTStrICmp(ValueUnion.psz, "sb16")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioController)(AudioControllerType_SB16)); + else if (!RTStrICmp(ValueUnion.psz, "ac97")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioController)(AudioControllerType_AC97)); + else if (!RTStrICmp(ValueUnion.psz, "hda")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioController)(AudioControllerType_HDA)); + else + { + errorArgument(ModifyVM::tr("Invalid --audiocontroller argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_AUDIOCODEC: + { + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> audioAdapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(audioAdapter.asOutParam())); + ASSERT(audioAdapter); + + if (!RTStrICmp(ValueUnion.psz, "sb16")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioCodec)(AudioCodecType_SB16)); + else if (!RTStrICmp(ValueUnion.psz, "stac9700")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioCodec)(AudioCodecType_STAC9700)); + else if (!RTStrICmp(ValueUnion.psz, "ad1980")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioCodec)(AudioCodecType_AD1980)); + else if (!RTStrICmp(ValueUnion.psz, "stac9221")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioCodec)(AudioCodecType_STAC9221)); + else + { + errorArgument(ModifyVM::tr("Invalid --audiocodec argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_AUDIODRIVER: + RT_FALL_THROUGH(); + case MODIFYVM_AUDIO: /** @todo Deprecated; remove. */ + { + if (c == MODIFYVM_AUDIO) + RTStrmPrintf(g_pStdErr, + ModifyVM::tr("Warning: --audio is deprecated and will be removed soon. Use --audio-driver instead!\n")); + + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> audioAdapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(audioAdapter.asOutParam())); + ASSERT(audioAdapter); + /* disable? */ + if ( !RTStrICmp(ValueUnion.psz, "none") + || !RTStrICmp(ValueUnion.psz, "null")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_Null)); + else if (!RTStrICmp(ValueUnion.psz, "default")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_Default)); +#ifdef RT_OS_WINDOWS +# ifdef VBOX_WITH_WINMM + else if (!RTStrICmp(ValueUnion.psz, "winmm")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_WinMM)); +# endif + else if (!RTStrICmp(ValueUnion.psz, "dsound")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_DirectSound)); + else if (!RTStrICmp(ValueUnion.psz, "was")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_WAS)); +#endif /* RT_OS_WINDOWS */ +#ifdef VBOX_WITH_AUDIO_OSS + else if (!RTStrICmp(ValueUnion.psz, "oss")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_OSS)); +#endif +#ifdef VBOX_WITH_AUDIO_ALSA + else if (!RTStrICmp(ValueUnion.psz, "alsa")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_ALSA)); +#endif +#ifdef VBOX_WITH_AUDIO_PULSE + else if (!RTStrICmp(ValueUnion.psz, "pulse")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_Pulse)); +#endif +#ifdef RT_OS_DARWIN + else if (!RTStrICmp(ValueUnion.psz, "coreaudio")) + CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_CoreAudio)); +#endif /* !RT_OS_DARWIN */ + else + { + errorArgument(ModifyVM::tr("Invalid %s argument '%s'"), + c == MODIFYVM_AUDIO ? "--audio" : "--audio-driver", ValueUnion.psz); + hrc = E_FAIL; + } + + if ( SUCCEEDED(hrc) + && c == MODIFYVM_AUDIO) /* To keep the original behavior until we remove the command. */ + CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(RTStrICmp(ValueUnion.psz, "none") == false ? false : true)); + + break; + } + + case MODIFYVM_AUDIOENABLED: + { + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> audioAdapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(audioAdapter.asOutParam())); + ASSERT(audioAdapter); + + CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_AUDIOIN: + { + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> audioAdapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(audioAdapter.asOutParam())); + ASSERT(audioAdapter); + + CHECK_ERROR(audioAdapter, COMSETTER(EnabledIn)(ValueUnion.f)); + break; + } + + case MODIFYVM_AUDIOOUT: + { + ComPtr<IAudioSettings> audioSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(AudioSettings)(audioSettings.asOutParam())); + ComPtr<IAudioAdapter> audioAdapter; + CHECK_ERROR_BREAK(audioSettings, COMGETTER(Adapter)(audioAdapter.asOutParam())); + ASSERT(audioAdapter); + + CHECK_ERROR(audioAdapter, COMSETTER(EnabledOut)(ValueUnion.f)); + break; + } + +#ifdef VBOX_WITH_SHARED_CLIPBOARD + case MODIFYVM_CLIPBOARD_MODE: + { + ClipboardMode_T mode = ClipboardMode_Disabled; /* Shut up MSC */ + if (!RTStrICmp(ValueUnion.psz, "disabled")) + mode = ClipboardMode_Disabled; + else if (!RTStrICmp(ValueUnion.psz, "hosttoguest")) + mode = ClipboardMode_HostToGuest; + else if (!RTStrICmp(ValueUnion.psz, "guesttohost")) + mode = ClipboardMode_GuestToHost; + else if (!RTStrICmp(ValueUnion.psz, "bidirectional")) + mode = ClipboardMode_Bidirectional; + else + { + errorArgument(ModifyVM::tr("Invalid --clipboard-mode argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(sessionMachine, COMSETTER(ClipboardMode)(mode)); + } + break; + } + +# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS + case MODIFYVM_CLIPBOARD_FILE_TRANSFERS: + { + BOOL fEnabled = false; /* Shut up MSC */ + if (!RTStrICmp(ValueUnion.psz, "enabled")) + fEnabled = true; + else if (!RTStrICmp(ValueUnion.psz, "disabled")) + fEnabled = false; + else + { + errorArgument(ModifyVM::tr("Invalid --clipboard-file-transfers argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(sessionMachine, COMSETTER(ClipboardFileTransfersEnabled)(fEnabled)); + } + break; + } +# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */ +#endif /* VBOX_WITH_SHARED_CLIPBOARD */ + + case MODIFYVM_DRAGANDDROP: + { + DnDMode_T mode = DnDMode_Disabled; /* Shut up MSC */ + if (!RTStrICmp(ValueUnion.psz, "disabled")) + mode = DnDMode_Disabled; + else if (!RTStrICmp(ValueUnion.psz, "hosttoguest")) + mode = DnDMode_HostToGuest; + else if (!RTStrICmp(ValueUnion.psz, "guesttohost")) + mode = DnDMode_GuestToHost; + else if (!RTStrICmp(ValueUnion.psz, "bidirectional")) + mode = DnDMode_Bidirectional; + else + { + errorArgument(ModifyVM::tr("Invalid --draganddrop argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(sessionMachine, COMSETTER(DnDMode)(mode)); + } + break; + } + + case MODIFYVM_VRDE_EXTPACK: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + if (vrdeServer) + { + if (RTStrICmp(ValueUnion.psz, "default") != 0) + { + Bstr bstr(ValueUnion.psz); + CHECK_ERROR(vrdeServer, COMSETTER(VRDEExtPack)(bstr.raw())); + } + else + CHECK_ERROR(vrdeServer, COMSETTER(VRDEExtPack)(Bstr().raw())); + } + break; + } + + case MODIFYVM_VRDEPROPERTY: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + if (vrdeServer) + { + /* Parse 'name=value' */ + char *pszProperty = RTStrDup(ValueUnion.psz); + if (pszProperty) + { + char *pDelimiter = strchr(pszProperty, '='); + if (pDelimiter) + { + *pDelimiter = '\0'; + + Bstr bstrName = pszProperty; + Bstr bstrValue = &pDelimiter[1]; + CHECK_ERROR(vrdeServer, SetVRDEProperty(bstrName.raw(), bstrValue.raw())); + } + else + { + RTStrFree(pszProperty); + + errorArgument(ModifyVM::tr("Invalid --vrdeproperty argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + break; + } + RTStrFree(pszProperty); + } + else + { + RTStrmPrintf(g_pStdErr, ModifyVM::tr("Error: Failed to allocate memory for VRDE property '%s'\n"), + ValueUnion.psz); + hrc = E_FAIL; + } + } + break; + } + + case MODIFYVM_VRDPPORT: + vrdeWarningDeprecatedOption("port"); + RT_FALL_THRU(); + + case MODIFYVM_VRDEPORT: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + if (!RTStrICmp(ValueUnion.psz, "default")) + CHECK_ERROR(vrdeServer, SetVRDEProperty(Bstr("TCP/Ports").raw(), Bstr("0").raw())); + else + CHECK_ERROR(vrdeServer, SetVRDEProperty(Bstr("TCP/Ports").raw(), Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_VRDPADDRESS: + vrdeWarningDeprecatedOption("address"); + RT_FALL_THRU(); + + case MODIFYVM_VRDEADDRESS: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + CHECK_ERROR(vrdeServer, SetVRDEProperty(Bstr("TCP/Address").raw(), Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_VRDPAUTHTYPE: + vrdeWarningDeprecatedOption("authtype"); + RT_FALL_THRU(); + case MODIFYVM_VRDEAUTHTYPE: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + if (!RTStrICmp(ValueUnion.psz, "null")) + { + CHECK_ERROR(vrdeServer, COMSETTER(AuthType)(AuthType_Null)); + } + else if (!RTStrICmp(ValueUnion.psz, "external")) + { + CHECK_ERROR(vrdeServer, COMSETTER(AuthType)(AuthType_External)); + } + else if (!RTStrICmp(ValueUnion.psz, "guest")) + { + CHECK_ERROR(vrdeServer, COMSETTER(AuthType)(AuthType_Guest)); + } + else + { + errorArgument(ModifyVM::tr("Invalid --vrdeauthtype argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_VRDEAUTHLIBRARY: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + if (vrdeServer) + { + if (RTStrICmp(ValueUnion.psz, "default") != 0) + { + Bstr bstr(ValueUnion.psz); + CHECK_ERROR(vrdeServer, COMSETTER(AuthLibrary)(bstr.raw())); + } + else + CHECK_ERROR(vrdeServer, COMSETTER(AuthLibrary)(Bstr().raw())); + } + break; + } + + case MODIFYVM_VRDPMULTICON: + vrdeWarningDeprecatedOption("multicon"); + RT_FALL_THRU(); + case MODIFYVM_VRDEMULTICON: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + CHECK_ERROR(vrdeServer, COMSETTER(AllowMultiConnection)(ValueUnion.f)); + break; + } + + case MODIFYVM_VRDPREUSECON: + vrdeWarningDeprecatedOption("reusecon"); + RT_FALL_THRU(); + case MODIFYVM_VRDEREUSECON: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + CHECK_ERROR(vrdeServer, COMSETTER(ReuseSingleConnection)(ValueUnion.f)); + break; + } + + case MODIFYVM_VRDPVIDEOCHANNEL: + vrdeWarningDeprecatedOption("videochannel"); + RT_FALL_THRU(); + case MODIFYVM_VRDEVIDEOCHANNEL: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + CHECK_ERROR(vrdeServer, SetVRDEProperty(Bstr("VideoChannel/Enabled").raw(), + ValueUnion.f? Bstr("true").raw(): Bstr("false").raw())); + break; + } + + case MODIFYVM_VRDPVIDEOCHANNELQUALITY: + vrdeWarningDeprecatedOption("videochannelquality"); + RT_FALL_THRU(); + case MODIFYVM_VRDEVIDEOCHANNELQUALITY: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + CHECK_ERROR(vrdeServer, SetVRDEProperty(Bstr("VideoChannel/Quality").raw(), + Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_VRDP: + vrdeWarningDeprecatedOption(""); + RT_FALL_THRU(); + case MODIFYVM_VRDE: + { + ComPtr<IVRDEServer> vrdeServer; + sessionMachine->COMGETTER(VRDEServer)(vrdeServer.asOutParam()); + ASSERT(vrdeServer); + + CHECK_ERROR(vrdeServer, COMSETTER(Enabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_USBRENAME: + { + const char *pszName = ValueUnion.psz; + int vrc = RTGetOptFetchValue(&GetOptState, &ValueUnion, RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorSyntax(ModifyVM::tr("Missing or invalid argument to '%s'"), + GetOptState.pDef->pszLong); + const char *pszNewName = ValueUnion.psz; + + SafeIfaceArray<IUSBController> ctrls; + CHECK_ERROR(sessionMachine, COMGETTER(USBControllers)(ComSafeArrayAsOutParam(ctrls))); + bool fRenamed = false; + for (size_t i = 0; i < ctrls.size(); i++) + { + ComPtr<IUSBController> pCtrl = ctrls[i]; + Bstr bstrName; + CHECK_ERROR(pCtrl, COMGETTER(Name)(bstrName.asOutParam())); + if (bstrName == pszName) + { + bstrName = pszNewName; + CHECK_ERROR(pCtrl, COMSETTER(Name)(bstrName.raw())); + fRenamed = true; + } + } + if (!fRenamed) + { + errorArgument(ModifyVM::tr("Invalid --usbrename parameters, nothing renamed")); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_USBXHCI: + { + ULONG cXhciCtrls = 0; + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_XHCI, &cXhciCtrls); + if (SUCCEEDED(hrc)) + { + if (!cXhciCtrls && ValueUnion.f) + { + ComPtr<IUSBController> UsbCtl; + CHECK_ERROR(sessionMachine, AddUSBController(Bstr("xHCI").raw(), USBControllerType_XHCI, + UsbCtl.asOutParam())); + } + else if (cXhciCtrls && !ValueUnion.f) + { + SafeIfaceArray<IUSBController> ctrls; + CHECK_ERROR(sessionMachine, COMGETTER(USBControllers)(ComSafeArrayAsOutParam(ctrls))); + for (size_t i = 0; i < ctrls.size(); i++) + { + ComPtr<IUSBController> pCtrl = ctrls[i]; + USBControllerType_T enmType; + CHECK_ERROR(pCtrl, COMGETTER(Type)(&enmType)); + if (enmType == USBControllerType_XHCI) + { + Bstr ctrlName; + CHECK_ERROR(pCtrl, COMGETTER(Name)(ctrlName.asOutParam())); + CHECK_ERROR(sessionMachine, RemoveUSBController(ctrlName.raw())); + } + } + } + } + break; + } + + case MODIFYVM_USBEHCI: + { + ULONG cEhciCtrls = 0; + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_EHCI, &cEhciCtrls); + if (SUCCEEDED(hrc)) + { + if (!cEhciCtrls && ValueUnion.f) + { + ComPtr<IUSBController> UsbCtl; + CHECK_ERROR(sessionMachine, AddUSBController(Bstr("EHCI").raw(), USBControllerType_EHCI, + UsbCtl.asOutParam())); + } + else if (cEhciCtrls && !ValueUnion.f) + { + SafeIfaceArray<IUSBController> ctrls; + CHECK_ERROR(sessionMachine, COMGETTER(USBControllers)(ComSafeArrayAsOutParam(ctrls))); + for (size_t i = 0; i < ctrls.size(); i++) + { + ComPtr<IUSBController> pCtrl = ctrls[i]; + USBControllerType_T enmType; + CHECK_ERROR(pCtrl, COMGETTER(Type)(&enmType)); + if (enmType == USBControllerType_EHCI) + { + Bstr ctrlName; + CHECK_ERROR(pCtrl, COMGETTER(Name)(ctrlName.asOutParam())); + CHECK_ERROR(sessionMachine, RemoveUSBController(ctrlName.raw())); + } + } + } + } + break; + } + + case MODIFYVM_USBOHCI: + { + ULONG cOhciCtrls = 0; + hrc = sessionMachine->GetUSBControllerCountByType(USBControllerType_OHCI, &cOhciCtrls); + if (SUCCEEDED(hrc)) + { + if (!cOhciCtrls && ValueUnion.f) + { + ComPtr<IUSBController> UsbCtl; + CHECK_ERROR(sessionMachine, AddUSBController(Bstr("OHCI").raw(), USBControllerType_OHCI, + UsbCtl.asOutParam())); + } + else if (cOhciCtrls && !ValueUnion.f) + { + SafeIfaceArray<IUSBController> ctrls; + CHECK_ERROR(sessionMachine, COMGETTER(USBControllers)(ComSafeArrayAsOutParam(ctrls))); + for (size_t i = 0; i < ctrls.size(); i++) + { + ComPtr<IUSBController> pCtrl = ctrls[i]; + USBControllerType_T enmType; + CHECK_ERROR(pCtrl, COMGETTER(Type)(&enmType)); + if (enmType == USBControllerType_OHCI) + { + Bstr ctrlName; + CHECK_ERROR(pCtrl, COMGETTER(Name)(ctrlName.asOutParam())); + CHECK_ERROR(sessionMachine, RemoveUSBController(ctrlName.raw())); + } + } + } + } + break; + } + + case MODIFYVM_SNAPSHOTFOLDER: + { + if (!RTStrICmp(ValueUnion.psz, "default")) + CHECK_ERROR(sessionMachine, COMSETTER(SnapshotFolder)(Bstr().raw())); + else + CHECK_ERROR(sessionMachine, COMSETTER(SnapshotFolder)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_TELEPORTER_ENABLED: + { + CHECK_ERROR(sessionMachine, COMSETTER(TeleporterEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_TELEPORTER_PORT: + { + CHECK_ERROR(sessionMachine, COMSETTER(TeleporterPort)(ValueUnion.u32)); + break; + } + + case MODIFYVM_TELEPORTER_ADDRESS: + { + CHECK_ERROR(sessionMachine, COMSETTER(TeleporterAddress)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_TELEPORTER_PASSWORD: + { + CHECK_ERROR(sessionMachine, COMSETTER(TeleporterPassword)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_TELEPORTER_PASSWORD_FILE: + { + Utf8Str password; + RTEXITCODE rcExit = readPasswordFile(ValueUnion.psz, &password); + if (rcExit != RTEXITCODE_SUCCESS) + hrc = E_FAIL; + else + CHECK_ERROR(sessionMachine, COMSETTER(TeleporterPassword)(Bstr(password).raw())); + break; + } + + case MODIFYVM_TRACING_ENABLED: + { + CHECK_ERROR(sessionMachine, COMSETTER(TracingEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_TRACING_CONFIG: + { + CHECK_ERROR(sessionMachine, COMSETTER(TracingConfig)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_TRACING_ALLOW_VM_ACCESS: + { + CHECK_ERROR(sessionMachine, COMSETTER(AllowTracingToAccessVM)(ValueUnion.f)); + break; + } + + case MODIFYVM_HARDWARE_UUID: + { + CHECK_ERROR(sessionMachine, COMSETTER(HardwareUUID)(Bstr(ValueUnion.psz).raw())); + break; + } + + case MODIFYVM_HPET: + { + CHECK_ERROR(sessionMachine, COMSETTER(HPETEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_IOCACHE: + { + CHECK_ERROR(sessionMachine, COMSETTER(IOCacheEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_IOCACHESIZE: + { + CHECK_ERROR(sessionMachine, COMSETTER(IOCacheSize)(ValueUnion.u32)); + break; + } + + case MODIFYVM_CHIPSET: + { + if (!RTStrICmp(ValueUnion.psz, "piix3")) + { + CHECK_ERROR(sessionMachine, COMSETTER(ChipsetType)(ChipsetType_PIIX3)); + } + else if (!RTStrICmp(ValueUnion.psz, "ich9")) + { + CHECK_ERROR(sessionMachine, COMSETTER(ChipsetType)(ChipsetType_ICH9)); + BOOL fIoApic = FALSE; + CHECK_ERROR(biosSettings, COMGETTER(IOAPICEnabled)(&fIoApic)); + if (!fIoApic) + { + RTStrmPrintf(g_pStdErr, ModifyVM::tr("*** I/O APIC must be enabled for ICH9, enabling. ***\n")); + CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(TRUE)); + } + } + else + { + errorArgument(ModifyVM::tr("Invalid --chipset argument '%s' (valid: piix3,ich9)"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } +#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL) + case MODIFYVM_IOMMU: + { + if ( !RTStrICmp(ValueUnion.psz, "none") + || !RTStrICmp(ValueUnion.psz, "disabled")) + CHECK_ERROR(sessionMachine, COMSETTER(IommuType)(IommuType_None)); + else if (!RTStrICmp(ValueUnion.psz, "amd")) + CHECK_ERROR(sessionMachine, COMSETTER(IommuType)(IommuType_AMD)); + else if (!RTStrICmp(ValueUnion.psz, "intel")) + { +#ifdef VBOX_WITH_IOMMU_INTEL + CHECK_ERROR(sessionMachine, COMSETTER(IommuType)(IommuType_Intel)); +#else + errorArgument(ModifyVM::tr("Invalid --iommu argument '%s' (valid: none,amd,automatic)"), ValueUnion.psz); + hrc = E_FAIL; +#endif + } + else if (!RTStrICmp(ValueUnion.psz, "automatic")) + { + CHECK_ERROR(sessionMachine, COMSETTER(IommuType)(IommuType_Automatic)); +#ifndef VBOX_WITH_IOMMU_INTEL + RTStrmPrintf(g_pStdErr, + ModifyVM::tr("Warning: On Intel hosts, 'automatic' will not enable an IOMMU since the Intel IOMMU device is not supported yet.\n")); +#endif + } + else + { + errorArgument(ModifyVM::tr("Invalid --iommu argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } +#endif +#if defined(VBOX_WITH_TPM) + case MODIFYVM_TPM_TYPE: + { + ComPtr<ITrustedPlatformModule> tpm; + sessionMachine->COMGETTER(TrustedPlatformModule)(tpm.asOutParam()); + + if ( !RTStrICmp(ValueUnion.psz, "none") + || !RTStrICmp(ValueUnion.psz, "disabled")) + CHECK_ERROR(tpm, COMSETTER(Type)(TpmType_None)); + else if (!RTStrICmp(ValueUnion.psz, "1.2")) + CHECK_ERROR(tpm, COMSETTER(Type)(TpmType_v1_2)); + else if (!RTStrICmp(ValueUnion.psz, "2.0")) + CHECK_ERROR(tpm, COMSETTER(Type)(TpmType_v2_0)); + else if (!RTStrICmp(ValueUnion.psz, "host")) + CHECK_ERROR(tpm, COMSETTER(Type)(TpmType_Host)); + else if (!RTStrICmp(ValueUnion.psz, "swtpm")) + CHECK_ERROR(tpm, COMSETTER(Type)(TpmType_Swtpm)); + else + { + errorArgument(ModifyVM::tr("Invalid --tpm-type argument '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + break; + } + + case MODIFYVM_TPM_LOCATION: + { + ComPtr<ITrustedPlatformModule> tpm; + sessionMachine->COMGETTER(TrustedPlatformModule)(tpm.asOutParam()); + + CHECK_ERROR(tpm, COMSETTER(Location)(Bstr(ValueUnion.psz).raw())); + break; + } +#endif +#ifdef VBOX_WITH_RECORDING + case MODIFYVM_RECORDING: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_SCREENS: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_FILENAME: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_VIDEO_WIDTH: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_VIDEO_HEIGHT: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_VIDEO_RES: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_VIDEO_RATE: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_VIDEO_FPS: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_MAXTIME: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_MAXSIZE: + RT_FALL_THROUGH(); + case MODIFYVM_RECORDING_OPTIONS: + { + ComPtr<IRecordingSettings> recordingSettings; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(RecordingSettings)(recordingSettings.asOutParam())); + SafeIfaceArray <IRecordingScreenSettings> saRecordingScreenScreens; + CHECK_ERROR_BREAK(recordingSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saRecordingScreenScreens))); + + switch (c) + { + case MODIFYVM_RECORDING: + { + CHECK_ERROR(recordingSettings, COMSETTER(Enabled)(ValueUnion.f)); + break; + } + case MODIFYVM_RECORDING_SCREENS: + { + ULONG cMonitors = 64; + CHECK_ERROR(pGraphicsAdapter, COMGETTER(MonitorCount)(&cMonitors)); + com::SafeArray<BOOL> screens(cMonitors); + if (RT_FAILURE(parseScreens(ValueUnion.psz, &screens))) + { + errorArgument(ModifyVM::tr("Invalid list of screens specified\n")); + hrc = E_FAIL; + break; + } + + if (cMonitors > saRecordingScreenScreens.size()) /* Paranoia. */ + cMonitors = (ULONG)saRecordingScreenScreens.size(); + + for (size_t i = 0; i < cMonitors; ++i) + CHECK_ERROR_BREAK(saRecordingScreenScreens[i], COMSETTER(Enabled)(screens[i])); + break; + } + case MODIFYVM_RECORDING_FILENAME: + { + Bstr bstr; + /* empty string will fall through, leaving bstr empty */ + if (*ValueUnion.psz) + { + char szVCFileAbs[RTPATH_MAX] = ""; + int vrc = RTPathAbs(ValueUnion.psz, szVCFileAbs, sizeof(szVCFileAbs)); + if (RT_FAILURE(vrc)) + { + errorArgument(ModifyVM::tr("Cannot convert filename \"%s\" to absolute path\n"), ValueUnion.psz); + hrc = E_FAIL; + break; + } + bstr = szVCFileAbs; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(Filename)(bstr.raw())); + break; + } + case MODIFYVM_RECORDING_VIDEO_WIDTH: + { + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(VideoWidth)(ValueUnion.u32)); + break; + } + case MODIFYVM_RECORDING_VIDEO_HEIGHT: + { + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(VideoHeight)(ValueUnion.u32)); + break; + } + case MODIFYVM_RECORDING_VIDEO_RES: + { + uint32_t uWidth = 0; + char *pszNext; + int vrc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 0, &uWidth); + if (RT_FAILURE(vrc) || vrc != VWRN_TRAILING_CHARS || !pszNext || *pszNext != 'x') + { + errorArgument(ModifyVM::tr("Error parsing video resolution '%s' (expected <width>x<height>)"), + ValueUnion.psz); + hrc = E_FAIL; + break; + } + uint32_t uHeight = 0; + vrc = RTStrToUInt32Ex(pszNext+1, NULL, 0, &uHeight); + if (vrc != VINF_SUCCESS) + { + errorArgument(ModifyVM::tr("Error parsing video resolution '%s' (expected <width>x<height>)"), + ValueUnion.psz); + hrc = E_FAIL; + break; + } + + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + { + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(VideoWidth)(uWidth)); + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(VideoHeight)(uHeight)); + } + break; + } + case MODIFYVM_RECORDING_VIDEO_RATE: + { + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(VideoRate)(ValueUnion.u32)); + break; + } + case MODIFYVM_RECORDING_VIDEO_FPS: + { + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(VideoFPS)(ValueUnion.u32)); + break; + } + case MODIFYVM_RECORDING_MAXTIME: + { + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(MaxTime)(ValueUnion.u32)); + break; + } + case MODIFYVM_RECORDING_MAXSIZE: + { + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(MaxFileSize)(ValueUnion.u32)); + break; + } + case MODIFYVM_RECORDING_OPTIONS: + { + Bstr bstr(ValueUnion.psz); + for (size_t i = 0; i < saRecordingScreenScreens.size(); ++i) + CHECK_ERROR(saRecordingScreenScreens[i], COMSETTER(Options)(bstr.raw())); + break; + } + } + + break; + } +#endif + case MODIFYVM_AUTOSTART_ENABLED: + { + CHECK_ERROR(sessionMachine, COMSETTER(AutostartEnabled)(ValueUnion.f)); + break; + } + + case MODIFYVM_AUTOSTART_DELAY: + { + CHECK_ERROR(sessionMachine, COMSETTER(AutostartDelay)(ValueUnion.u32)); + break; + } + + case MODIFYVM_AUTOSTOP_TYPE: + { + AutostopType_T enmAutostopType = AutostopType_Disabled; + + if (!RTStrICmp(ValueUnion.psz, "disabled")) + enmAutostopType = AutostopType_Disabled; + else if (!RTStrICmp(ValueUnion.psz, "savestate")) + enmAutostopType = AutostopType_SaveState; + else if (!RTStrICmp(ValueUnion.psz, "poweroff")) + enmAutostopType = AutostopType_PowerOff; + else if (!RTStrICmp(ValueUnion.psz, "acpishutdown")) + enmAutostopType = AutostopType_AcpiShutdown; + else + { + errorArgument(ModifyVM::tr("Invalid --autostop-type argument '%s' (valid: disabled, savestate, poweroff, acpishutdown)"), + ValueUnion.psz); + hrc = E_FAIL; + } + + if (SUCCEEDED(hrc)) + CHECK_ERROR(sessionMachine, COMSETTER(AutostopType)(enmAutostopType)); + break; + } +#ifdef VBOX_WITH_PCI_PASSTHROUGH + case MODIFYVM_ATTACH_PCI: + { + const char* pAt = strchr(ValueUnion.psz, '@'); + int32_t iHostAddr, iGuestAddr; + + iHostAddr = parsePci(ValueUnion.psz); + iGuestAddr = pAt != NULL ? parsePci(pAt + 1) : iHostAddr; + + if (iHostAddr == -1 || iGuestAddr == -1) + { + errorArgument(ModifyVM::tr("Invalid --pciattach argument '%s' (valid: 'HB:HD.HF@GB:GD.GF' or just 'HB:HD.HF')"), + ValueUnion.psz); + hrc = E_FAIL; + } + else + { + CHECK_ERROR(sessionMachine, AttachHostPCIDevice(iHostAddr, iGuestAddr, TRUE)); + } + + break; + } + case MODIFYVM_DETACH_PCI: + { + int32_t iHostAddr; + + iHostAddr = parsePci(ValueUnion.psz); + if (iHostAddr == -1) + { + errorArgument(ModifyVM::tr("Invalid --pcidetach argument '%s' (valid: 'HB:HD.HF')"), ValueUnion.psz); + hrc = E_FAIL; + } + else + { + CHECK_ERROR(sessionMachine, DetachHostPCIDevice(iHostAddr)); + } + + break; + } +#endif + +#ifdef VBOX_WITH_USB_CARDREADER + case MODIFYVM_USBCARDREADER: + { + CHECK_ERROR(sessionMachine, COMSETTER(EmulatedUSBCardReaderEnabled)(ValueUnion.f)); + break; + } +#endif /* VBOX_WITH_USB_CARDREADER */ + + case MODIFYVM_DEFAULTFRONTEND: + { + Bstr bstr(ValueUnion.psz); + if (bstr == "default") + bstr = Bstr::Empty; + CHECK_ERROR(sessionMachine, COMSETTER(DefaultFrontend)(bstr.raw())); + break; + } + + case MODIFYVM_VMPROC_PRIORITY: + { + VMProcPriority_T enmPriority = nameToVMProcPriority(ValueUnion.psz); + if (enmPriority == VMProcPriority_Invalid) + { + errorArgument(ModifyVM::tr("Invalid --vm-process-priority '%s'"), ValueUnion.psz); + hrc = E_FAIL; + } + else + { + CHECK_ERROR(sessionMachine, COMSETTER(VMProcessPriority)(enmPriority)); + } + break; + } + + case MODIFYVM_TESTING_ENABLED: + hrc = setExtraData(sessionMachine, "VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled", ValueUnion.f ? "1" : ""); + break; + + case MODIFYVM_TESTING_MMIO: + hrc = setExtraData(sessionMachine, "VBoxInternal/Devices/VMMDev/0/Config/TestingMMIO", ValueUnion.f ? "1" : ""); + break; + + case MODIFYVM_TESTING_CFG_DWORD: + if (GetOptState.uIndex <= 9) + { + char szVar[128]; + RTStrPrintf(szVar, sizeof(szVar), "VBoxInternal/Devices/VMMDev/0/Config/TestingCfgDword%u", + GetOptState.uIndex); + char szValue[32]; + RTStrPrintf(szValue, sizeof(szValue), "%u", ValueUnion.u32); + hrc = setExtraData(sessionMachine, szVar, szValue); + } + else + hrc = errorArgumentHr(ModifyVM::tr("--testing-cfg-dword index %u is out of range: 0 thru 9"), + GetOptState.uIndex); + break; + + case MODIFYVM_GUEST_DEBUG_PROVIDER: + { + ComPtr<IGuestDebugControl> gstDbgCtrl; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(GuestDebugControl)(gstDbgCtrl.asOutParam())); + + GuestDebugProvider_T enmDebugProvider = GuestDebugProvider_None; + + if (!RTStrICmp(ValueUnion.psz, "none")) + enmDebugProvider = GuestDebugProvider_None; + else if (!RTStrICmp(ValueUnion.psz, "native")) + enmDebugProvider = GuestDebugProvider_Native; + else if (!RTStrICmp(ValueUnion.psz, "gdb")) + enmDebugProvider = GuestDebugProvider_GDB; + else if (!RTStrICmp(ValueUnion.psz, "kd")) + enmDebugProvider = GuestDebugProvider_KD; + else + { + errorArgument(ModifyVM::tr("Invalid --guest-debug-provider '%s' (valid: none, native, gdb, kd)"), + ValueUnion.psz); + hrc = E_FAIL; + } + + if (SUCCEEDED(hrc)) + CHECK_ERROR(gstDbgCtrl, COMSETTER(DebugProvider)(enmDebugProvider)); + break; + } + + case MODIFYVM_GUEST_DEBUG_IO_PROVIDER: + { + ComPtr<IGuestDebugControl> gstDbgCtrl; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(GuestDebugControl)(gstDbgCtrl.asOutParam())); + + GuestDebugIoProvider_T enmDebugIoProvider = GuestDebugIoProvider_None; + + if (!RTStrICmp(ValueUnion.psz, "none")) + enmDebugIoProvider = GuestDebugIoProvider_None; + else if (!RTStrICmp(ValueUnion.psz, "tcp")) + enmDebugIoProvider = GuestDebugIoProvider_TCP; + else if (!RTStrICmp(ValueUnion.psz, "udp")) + enmDebugIoProvider = GuestDebugIoProvider_UDP; + else if (!RTStrICmp(ValueUnion.psz, "ipc")) + enmDebugIoProvider = GuestDebugIoProvider_IPC; + else + { + errorArgument(ModifyVM::tr("Invalid --guest-debug-io-provider '%s' (valid: none, tcp, udp, ipc)"), + ValueUnion.psz); + hrc = E_FAIL; + } + + if (SUCCEEDED(hrc)) + CHECK_ERROR(gstDbgCtrl, COMSETTER(DebugIoProvider)(enmDebugIoProvider)); + break; + } + + case MODIFYVM_GUEST_DEBUG_ADDRESS: + { + ComPtr<IGuestDebugControl> gstDbgCtrl; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(GuestDebugControl)(gstDbgCtrl.asOutParam())); + + Bstr bstr(ValueUnion.psz); + CHECK_ERROR(gstDbgCtrl, COMSETTER(DebugAddress)(bstr.raw())); + break; + } + + case MODIFYVM_GUEST_DEBUG_PORT: + { + ComPtr<IGuestDebugControl> gstDbgCtrl; + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(GuestDebugControl)(gstDbgCtrl.asOutParam())); + CHECK_ERROR(gstDbgCtrl, COMSETTER(DebugPort)(ValueUnion.u32)); + break; + } + + default: + errorGetOpt(c, &ValueUnion); + hrc = E_FAIL; + break; + } + } + + /* commit changes */ + if (SUCCEEDED(hrc)) + CHECK_ERROR(sessionMachine, SaveSettings()); + + /* it's important to always close sessions */ + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageNATNetwork.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageNATNetwork.cpp new file mode 100644 index 00000000..8f911fec --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageNATNetwork.cpp @@ -0,0 +1,702 @@ +/* $Id: VBoxManageNATNetwork.cpp $ */ +/** @file + * VBoxManage - Implementation of NAT Network command command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#ifndef RT_OS_WINDOWS +# include <netinet/in.h> +#else +/* from <ws2ipdef.h> */ +# define INET6_ADDRSTRLEN 65 +#endif + +#define IPv6 + +#include <iprt/cdefs.h> +#include <iprt/cidr.h> +#include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/net.h> +#include <iprt/getopt.h> +#include <iprt/ctype.h> + +#include <VBox/log.h> + +#include <algorithm> +#include <vector> +#include <iprt/sanitized/string> + +#include "VBoxManage.h" +#include "VBoxPortForwardString.h" + + +DECLARE_TRANSLATION_CONTEXT(Nat); + +using namespace com; + +typedef enum +{ + OP_ADD = 1000, + OP_REMOVE, + OP_MODIFY, + OP_START, + OP_STOP +} OPCODE; + +typedef struct PFNAME2DELETE +{ + char szName[PF_NAMELEN]; + bool fIPv6; +} PFNAME2DELETE, *PPFNAME2DELETE; + +typedef std::vector<PFNAME2DELETE> VPF2DELETE; +typedef VPF2DELETE::const_iterator VPF2DELETEITERATOR; + +typedef std::vector<PORTFORWARDRULE> VPF2ADD; +typedef VPF2ADD::const_iterator VPF2ADDITERATOR; + +typedef std::vector<std::string> LOOPBACK2DELETEADD; +typedef LOOPBACK2DELETEADD::iterator LOOPBACK2DELETEADDITERATOR; + +static HRESULT printNATNetwork(const ComPtr<INATNetwork> &pNATNet, + bool fLong = true) +{ + HRESULT hrc; + + do + { + Bstr strVal; + BOOL fVal; + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(NetworkName)(strVal.asOutParam())); + RTPrintf(Nat::tr("Name: %ls\n"), strVal.raw()); + + if (fLong) + { + /* + * What does it even mean for a natnet to be disabled? + * (rhetorical question). Anyway, don't print it unless + * asked for a complete dump. + */ + CHECK_ERROR_BREAK(pNATNet, COMGETTER(Enabled)(&fVal)); + RTPrintf(Nat::tr("Enabled: %s\n"), fVal ? Nat::tr("Yes") : Nat::tr("No")); + } + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(Network)(strVal.asOutParam())); + RTPrintf(Nat::tr("Network: %ls\n"), strVal.raw()); + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(Gateway)(strVal.asOutParam())); + RTPrintf(Nat::tr("Gateway: %ls\n"), strVal.raw()); + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(NeedDhcpServer)(&fVal)); + RTPrintf(Nat::tr("DHCP Server: %s\n"), fVal ? Nat::tr("Yes") : Nat::tr("No")); + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(IPv6Enabled)(&fVal)); + RTPrintf("IPv6: %s\n", fVal ? Nat::tr("Yes") : Nat::tr("No")); + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(IPv6Prefix)(strVal.asOutParam())); + RTPrintf(Nat::tr("IPv6 Prefix: %ls\n"), strVal.raw()); + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(&fVal)); + RTPrintf(Nat::tr("IPv6 Default: %s\n"), fVal ? Nat::tr("Yes") : Nat::tr("No")); + + + if (fLong) + { + com::SafeArray<BSTR> strs; + +#define PRINT_STRING_ARRAY(title) do { \ + if (strs.size() > 0) \ + { \ + RTPrintf(title); \ + for (size_t j = 0; j < strs.size(); ++j) \ + RTPrintf(" %s\n", Utf8Str(strs[j]).c_str()); \ + } \ + } while (0) + + CHECK_ERROR_BREAK(pNATNet, COMGETTER(PortForwardRules4)(ComSafeArrayAsOutParam(strs))); + PRINT_STRING_ARRAY(Nat::tr("Port-forwarding (ipv4)\n")); + strs.setNull(); + + CHECK_ERROR(pNATNet, COMGETTER(PortForwardRules6)(ComSafeArrayAsOutParam(strs))); + PRINT_STRING_ARRAY(Nat::tr("Port-forwarding (ipv6)\n")); + strs.setNull(); + + CHECK_ERROR(pNATNet, COMGETTER(LocalMappings)(ComSafeArrayAsOutParam(strs))); + PRINT_STRING_ARRAY(Nat::tr("loopback mappings (ipv4)\n")); + strs.setNull(); + +#undef PRINT_STRING_ARRAY + } + + RTPrintf("\n"); + } while (0); + + return hrc; +} + +static RTEXITCODE handleNATList(HandlerArg *a) +{ + HRESULT hrc; + + RTPrintf(Nat::tr("NAT Networks:\n\n")); + + const char *pszFilter = NULL; + if (a->argc > 1) + pszFilter = a->argv[1]; + + size_t cFound = 0; + + com::SafeIfaceArray<INATNetwork> arrNetNets; + CHECK_ERROR(a->virtualBox, COMGETTER(NATNetworks)(ComSafeArrayAsOutParam(arrNetNets))); + for (size_t i = 0; i < arrNetNets.size(); ++i) + { + ComPtr<INATNetwork> pNATNet = arrNetNets[i]; + + if (pszFilter) + { + Bstr strVal; + CHECK_ERROR_BREAK(pNATNet, COMGETTER(NetworkName)(strVal.asOutParam())); + + Utf8Str strValUTF8(strVal); + if (!RTStrSimplePatternMatch(pszFilter, strValUTF8.c_str())) + continue; + } + + hrc = printNATNetwork(pNATNet); + if (FAILED(hrc)) + break; + + cFound++; + } + + if (SUCCEEDED(hrc)) + RTPrintf(Nat::tr("%zu %s found\n"), cFound, cFound == 1 ? Nat::tr("network") : Nat::tr("networks", "", cFound)); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +static RTEXITCODE handleOp(HandlerArg *a, OPCODE enmCode) +{ + if (a->argc - 1 <= 1) + return errorSyntax(Nat::tr("Not enough parameters")); + + const char *pNetName = NULL; + const char *pPrefixIPv4 = NULL; + const char *pPrefixIPv6 = NULL; + int enable = -1; + int dhcp = -1; + int ipv6 = -1; + int ipv6_default = -1; + + VPF2DELETE vPfName2Delete; + VPF2ADD vPf2Add; + + LOOPBACK2DELETEADD vLoopback2Delete; + LOOPBACK2DELETEADD vLoopback2Add; + + LONG loopback6Offset = 0; /* ignore me */ + + enum + { + kNATNetworkIota = 1000, + kNATNetwork_IPv6Default, + kNATNetwork_IPv6Prefix, + }; + + static const RTGETOPTDEF g_aNATNetworkIPOptions[] = + { + { "--netname", 't', RTGETOPT_REQ_STRING }, + { "--network", 'n', RTGETOPT_REQ_STRING }, /* old name */ + { "--ipv4-prefix", 'n', RTGETOPT_REQ_STRING }, /* new name */ + { "--dhcp", 'h', RTGETOPT_REQ_BOOL }, + { "--ipv6", '6', RTGETOPT_REQ_BOOL }, /* old name */ + { "--ipv6-default", kNATNetwork_IPv6Default, RTGETOPT_REQ_BOOL }, + { "--ipv6-enable", '6', RTGETOPT_REQ_BOOL }, /* new name */ + { "--ipv6-prefix", kNATNetwork_IPv6Prefix, RTGETOPT_REQ_STRING }, + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "--disable", 'd', RTGETOPT_REQ_NOTHING }, + { "--port-forward-4", 'p', RTGETOPT_REQ_STRING }, + { "--port-forward-6", 'P', RTGETOPT_REQ_STRING }, + { "--loopback-4", 'l', RTGETOPT_REQ_STRING }, + { "--loopback-6", 'L', RTGETOPT_REQ_STRING }, + }; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, a->argc, a->argv, g_aNATNetworkIPOptions, + enmCode != OP_REMOVE ? RT_ELEMENTS(g_aNATNetworkIPOptions) : 4, /* we use only --netname and --ifname for remove*/ + 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 't': // --netname + if (pNetName) + return errorSyntax(Nat::tr("You can only specify --netname only once.")); + pNetName = ValueUnion.psz; + break; + + case 'n': // --network + if (pPrefixIPv4) + return errorSyntax(Nat::tr("You can only specify --network only once.")); + pPrefixIPv4 = ValueUnion.psz; + break; + + case 'e': // --enable + if (enable >= 0) + return errorSyntax(Nat::tr("You can specify either --enable or --disable once.")); + enable = 1; + break; + + case 'd': // --disable + if (enable >= 0) + return errorSyntax(Nat::tr("You can specify either --enable or --disable once.")); + enable = 0; + break; + + case 'h': + if (dhcp != -1) + return errorSyntax(Nat::tr("You can specify --dhcp only once.")); + dhcp = ValueUnion.f; + break; + + case '6': + if (ipv6 != -1) + return errorSyntax(Nat::tr("You can specify --ipv6 only once.")); + ipv6 = ValueUnion.f; + break; + + case kNATNetwork_IPv6Prefix: + if (pPrefixIPv6) + return errorSyntax(Nat::tr("You can specify --ipv6-prefix only once.")); + pPrefixIPv6 = ValueUnion.psz; + break; + + case kNATNetwork_IPv6Default: // XXX: uwe + if (ipv6_default != -1) + return errorSyntax(Nat::tr("You can specify --ipv6-default only once.")); + ipv6_default = ValueUnion.f; + break; + + case 'L': /* ipv6 loopback */ + case 'l': /* ipv4 loopback */ + if (RTStrCmp(ValueUnion.psz, "delete") == 0) + { + /* deletion */ + if (enmCode != OP_MODIFY) + errorSyntax(Nat::tr("loopback couldn't be deleted on modified\n")); + if (c == 'L') + loopback6Offset = -1; + else + { + int vrc; + RTGETOPTUNION Addr2Delete; + vrc = RTGetOptFetchValue(&GetState, + &Addr2Delete, + RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorSyntax(Nat::tr("Not enough parŠ°meters\n")); + + vLoopback2Delete.push_back(std::string(Addr2Delete.psz)); + } + } + else + { + /* addition */ + if (c == 'L') + loopback6Offset = ValueUnion.u32; + else + vLoopback2Add.push_back(std::string(ValueUnion.psz)); + } + break; + + case 'P': /* ipv6 portforwarding*/ + case 'p': /* ipv4 portforwarding */ + { + if (RTStrCmp(ValueUnion.psz, "delete") != 0) + { + /* addition */ + /* netPfStrToPf will clean up the Pfr */ + PORTFORWARDRULE Pfr; + int irc = netPfStrToPf(ValueUnion.psz, (c == 'P'), &Pfr); + if (RT_FAILURE(irc)) + return errorSyntax(Nat::tr("Invalid port-forward rule %s\n"), ValueUnion.psz); + + vPf2Add.push_back(Pfr); + } + else + { + /* deletion */ + if (enmCode != OP_MODIFY) + return errorSyntax(Nat::tr("Port-forward could be deleted on modify\n")); + + RTGETOPTUNION NamePf2DeleteUnion; + int vrc = RTGetOptFetchValue(&GetState, &NamePf2DeleteUnion, RTGETOPT_REQ_STRING); + if (RT_FAILURE(vrc)) + return errorSyntax(Nat::tr("Not enough parŠ°meters\n")); + + if (strlen(NamePf2DeleteUnion.psz) > PF_NAMELEN) + return errorSyntax(Nat::tr("Port-forward rule name is too long\n")); + + PFNAME2DELETE Name2Delete; + RT_ZERO(Name2Delete); + RTStrCopy(Name2Delete.szName, PF_NAMELEN, NamePf2DeleteUnion.psz); + Name2Delete.fIPv6 = (c == 'P'); + vPfName2Delete.push_back(Name2Delete); + } + break; + } + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if (!pNetName) + return errorSyntax(Nat::tr("You need to specify the --netname option")); + /* verification */ + switch (enmCode) + { + case OP_ADD: + if (!pPrefixIPv4) + return errorSyntax(Nat::tr("You need to specify the --network option")); + break; + case OP_MODIFY: + case OP_REMOVE: + case OP_START: + case OP_STOP: + break; + default: + AssertMsgFailedReturn((Nat::tr("Unknown operation (:%d)"), enmCode), RTEXITCODE_FAILURE); + } + + HRESULT hrc; + Bstr NetName; + NetName = Bstr(pNetName); + + ComPtr<INATNetwork> net; + hrc = a->virtualBox->FindNATNetworkByName(NetName.mutableRaw(), net.asOutParam()); + if (enmCode == OP_ADD) + { + if (SUCCEEDED(hrc)) + return errorArgument(Nat::tr("NATNetwork server already exists")); + + CHECK_ERROR(a->virtualBox, CreateNATNetwork(NetName.raw(), net.asOutParam())); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to create the NAT network service")); + } + else if (FAILED(hrc)) + return errorArgument(Nat::tr("NATNetwork server does not exist")); + + switch (enmCode) + { + case OP_ADD: + case OP_MODIFY: + { + if (pPrefixIPv4) + { + CHECK_ERROR(net, COMSETTER(Network)(Bstr(pPrefixIPv4).raw())); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + if (dhcp >= 0) + { + CHECK_ERROR(net, COMSETTER(NeedDhcpServer) ((BOOL)dhcp)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + + /* + * If we are asked to disable IPv6, do it early so that + * the same command can also set IPv6 prefix to empty if + * it so wishes. + */ + if (ipv6 == 0) + { + CHECK_ERROR(net, COMSETTER(IPv6Enabled)(FALSE)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + + if (pPrefixIPv6) + { + CHECK_ERROR(net, COMSETTER(IPv6Prefix)(Bstr(pPrefixIPv6).raw())); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + + /* + * If we are asked to enable IPv6, do it late, so that the + * same command can also set IPv6 prefix. + */ + if (ipv6 > 0) + { + CHECK_ERROR(net, COMSETTER(IPv6Enabled)(TRUE)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + + if (ipv6_default != -1) + { + BOOL fIPv6Default = RT_BOOL(ipv6_default); + CHECK_ERROR(net, COMSETTER(AdvertiseDefaultIPv6RouteEnabled)(fIPv6Default)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + + if (!vPfName2Delete.empty()) + { + VPF2DELETEITERATOR it; + for (it = vPfName2Delete.begin(); it != vPfName2Delete.end(); ++it) + { + CHECK_ERROR(net, RemovePortForwardRule((BOOL)(*it).fIPv6, + Bstr((*it).szName).raw())); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to delete pf")); + } + } + + if (!vPf2Add.empty()) + { + VPF2ADDITERATOR it; + for (it = vPf2Add.begin(); it != vPf2Add.end(); ++it) + { + NATProtocol_T proto = NATProtocol_TCP; + if ((*it).iPfrProto == IPPROTO_TCP) + proto = NATProtocol_TCP; + else if ((*it).iPfrProto == IPPROTO_UDP) + proto = NATProtocol_UDP; + else + continue; /* XXX: warning here. */ + + CHECK_ERROR(net, AddPortForwardRule((BOOL)(*it).fPfrIPv6, + Bstr((*it).szPfrName).raw(), + proto, + Bstr((*it).szPfrHostAddr).raw(), + (*it).u16PfrHostPort, + Bstr((*it).szPfrGuestAddr).raw(), + (*it).u16PfrGuestPort)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to add pf")); + } + } + + if (loopback6Offset) + { + if (loopback6Offset == -1) + loopback6Offset = 0; /* deletion */ + + CHECK_ERROR_RET(net, COMSETTER(LoopbackIp6)(loopback6Offset), RTEXITCODE_FAILURE); + } + + /* addLocalMapping (hostid, offset) */ + if (!vLoopback2Add.empty()) + { + /* we're expecting stings 127.0.0.1=5 */ + LOOPBACK2DELETEADDITERATOR it; + for (it = vLoopback2Add.begin(); + it != vLoopback2Add.end(); + ++it) + { + std::string address, strOffset; + size_t pos = it->find('='); + LONG lOffset = 0; + Bstr bstrAddress; + + AssertReturn(pos != std::string::npos, errorArgument(Nat::tr("invalid loopback string"))); + + address = it->substr(0, pos); + strOffset = it->substr(pos + 1); + + lOffset = RTStrToUInt32(strOffset.c_str()); + AssertReturn(lOffset > 0, errorArgument(Nat::tr("invalid loopback string"))); + + bstrAddress = Bstr(address.c_str()); + + CHECK_ERROR_RET(net, AddLocalMapping(bstrAddress.raw(), lOffset), RTEXITCODE_FAILURE); + } + } + + if (!vLoopback2Delete.empty()) + { + /* we're expecting stings 127.0.0.1 */ + LOOPBACK2DELETEADDITERATOR it; + for (it = vLoopback2Add.begin(); + it != vLoopback2Add.end(); + ++it) + { + Bstr bstrAddress; + bstrAddress = Bstr(it->c_str()); + + CHECK_ERROR_RET(net, AddLocalMapping(bstrAddress.raw(), 0), RTEXITCODE_FAILURE); + } + } + + if (enable >= 0) + { + CHECK_ERROR(net, COMSETTER(Enabled) ((BOOL)enable)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to set configuration")); + } + break; + } + case OP_REMOVE: + { + CHECK_ERROR(a->virtualBox, RemoveNATNetwork(net)); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to remove nat network")); + break; + } + case OP_START: + { + CHECK_ERROR(net, Start()); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to start network")); + break; + } + case OP_STOP: + { + CHECK_ERROR(net, Stop()); + if (FAILED(hrc)) + return errorArgument(Nat::tr("Failed to stop network")); + break; + } + default:; + } + return RTEXITCODE_SUCCESS; +} + + +/* + * VBoxManage natnetwork ... + */ +RTEXITCODE handleNATNetwork(HandlerArg *a) +{ + if (a->argc < 1) + return errorSyntax(Nat::tr("Not enough parameters")); + + RTEXITCODE rcExit; + if (strcmp(a->argv[0], "modify") == 0) + { + setCurrentSubcommand(HELP_SCOPE_NATNETWORK_MODIFY); + rcExit = handleOp(a, OP_MODIFY); + } + else if (strcmp(a->argv[0], "add") == 0) + { + setCurrentSubcommand(HELP_SCOPE_NATNETWORK_ADD); + rcExit = handleOp(a, OP_ADD); + } + else if (strcmp(a->argv[0], "remove") == 0) + { + setCurrentSubcommand(HELP_SCOPE_NATNETWORK_REMOVE); + rcExit = handleOp(a, OP_REMOVE); + } + else if (strcmp(a->argv[0], "start") == 0) + { + setCurrentSubcommand(HELP_SCOPE_NATNETWORK_START); + rcExit = handleOp(a, OP_START); + } + else if (strcmp(a->argv[0], "stop") == 0) + { + setCurrentSubcommand(HELP_SCOPE_NATNETWORK_STOP); + rcExit = handleOp(a, OP_STOP); + } + else if (strcmp(a->argv[0], "list") == 0) + { + setCurrentSubcommand(HELP_SCOPE_NATNETWORK_LIST); + rcExit = handleNATList(a); + } + else + rcExit = errorSyntax(Nat::tr("Invalid parameter '%s'"), a->argv[0]); + return rcExit; +} + + +/* + * VBoxManage list natnetworks ... + */ +RTEXITCODE listNATNetworks(bool fLong, bool fSorted, + const ComPtr<IVirtualBox> &pVirtualBox) +{ + HRESULT hrc; + + com::SafeIfaceArray<INATNetwork> aNets; + CHECK_ERROR_RET(pVirtualBox, + COMGETTER(NATNetworks)(ComSafeArrayAsOutParam(aNets)), + RTEXITCODE_FAILURE); + + const size_t cNets = aNets.size(); + if (cNets == 0) + return RTEXITCODE_SUCCESS; + + /* + * Sort the list if necessary. The sort is indirect via an + * intermediate array of indexes. + */ + std::vector<size_t> vIndexes(cNets); + for (size_t i = 0; i < cNets; ++i) + vIndexes[i] = i; + + if (fSorted) + { + std::vector<com::Bstr> vBstrNames(cNets); + for (size_t i = 0; i < cNets; ++i) + { + CHECK_ERROR_RET(aNets[i], + COMGETTER(NetworkName)(vBstrNames[i].asOutParam()), + RTEXITCODE_FAILURE); + } + + struct SortBy { + const std::vector<com::Bstr> &ks; + SortBy(const std::vector<com::Bstr> &aKeys) : ks(aKeys) {} + bool operator() (size_t l, size_t r) { return ks[l] < ks[r]; } + }; + + std::sort(vIndexes.begin(), vIndexes.end(), + SortBy(vBstrNames)); + } + + for (size_t i = 0; i < cNets; ++i) + { + printNATNetwork(aNets[vIndexes[i]], fLong); + } + + return RTEXITCODE_SUCCESS; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp new file mode 100644 index 00000000..69598c44 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp @@ -0,0 +1,670 @@ +/* $Id: VBoxManageSnapshot.cpp $ */ +/** @file + * VBoxManage - The 'snapshot' command. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> + +#include <VBox/com/VirtualBox.h> + +#include <iprt/getopt.h> +#include <iprt/stream.h> +#include <iprt/time.h> + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Snapshot); + +/** + * Helper function used with "VBoxManage snapshot ... dump". Gets called to find the + * snapshot in the machine's snapshot tree that uses a particular diff image child of + * a medium. + * Horribly inefficient since we keep re-querying the snapshots tree for each image, + * but this is for quick debugging only. + * @param pMedium + * @param pThisSnapshot + * @param pCurrentSnapshot + * @param uMediumLevel + * @param uSnapshotLevel + * @return + */ +bool FindAndPrintSnapshotUsingMedium(ComPtr<IMedium> &pMedium, + ComPtr<ISnapshot> &pThisSnapshot, + ComPtr<ISnapshot> &pCurrentSnapshot, + uint32_t uMediumLevel, + uint32_t uSnapshotLevel) +{ + HRESULT hrc; + + do + { + // get snapshot machine so we can figure out which diff image this created + ComPtr<IMachine> pSnapshotMachine; + CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Machine)(pSnapshotMachine.asOutParam())); + + // get media attachments + SafeIfaceArray<IMediumAttachment> aAttachments; + CHECK_ERROR_BREAK(pSnapshotMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aAttachments))); + + for (uint32_t i = 0; + i < aAttachments.size(); + ++i) + { + ComPtr<IMediumAttachment> pAttach(aAttachments[i]); + DeviceType_T type; + CHECK_ERROR_BREAK(pAttach, COMGETTER(Type)(&type)); + if (type == DeviceType_HardDisk) + { + ComPtr<IMedium> pMediumInSnapshot; + CHECK_ERROR_BREAK(pAttach, COMGETTER(Medium)(pMediumInSnapshot.asOutParam())); + + if (pMediumInSnapshot == pMedium) + { + // get snapshot name + Bstr bstrSnapshotName; + CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Name)(bstrSnapshotName.asOutParam())); + + RTPrintf("%*s \"%ls\"%s\n", + 50 + uSnapshotLevel * 2, "", // indent + bstrSnapshotName.raw(), + (pThisSnapshot == pCurrentSnapshot) ? " (CURSNAP)" : ""); + return true; // found + } + } + } + + // not found: then recurse into child snapshots + SafeIfaceArray<ISnapshot> aSnapshots; + CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Children)(ComSafeArrayAsOutParam(aSnapshots))); + + for (uint32_t i = 0; + i < aSnapshots.size(); + ++i) + { + ComPtr<ISnapshot> pChild(aSnapshots[i]); + if (FindAndPrintSnapshotUsingMedium(pMedium, + pChild, + pCurrentSnapshot, + uMediumLevel, + uSnapshotLevel + 1)) + // found: + break; + } + } while (0); + + return false; +} + +/** + * Helper function used with "VBoxManage snapshot ... dump". Called from DumpSnapshot() + * for each hard disk attachment found in a virtual machine. This then writes out the + * root (base) medium for that hard disk attachment and recurses into the children + * tree of that medium, correlating it with the snapshots of the machine. + * @param pCurrentStateMedium constant, the medium listed in the current machine data (latest diff image). + * @param pMedium variant, initially the base medium, then a child of the base medium when recursing. + * @param pRootSnapshot constant, the root snapshot of the machine, if any; this then looks into the child snapshots. + * @param pCurrentSnapshot constant, the machine's current snapshot (so we can mark it in the output). + * @param uLevel variant, the recursion level for output indentation. + */ +void DumpMediumWithChildren(ComPtr<IMedium> &pCurrentStateMedium, + ComPtr<IMedium> &pMedium, + ComPtr<ISnapshot> &pRootSnapshot, + ComPtr<ISnapshot> &pCurrentSnapshot, + uint32_t uLevel) +{ + HRESULT hrc; + do + { + // print this medium + Bstr bstrMediumName; + CHECK_ERROR_BREAK(pMedium, COMGETTER(Name)(bstrMediumName.asOutParam())); + RTPrintf("%*s \"%ls\"%s\n", + uLevel * 2, "", // indent + bstrMediumName.raw(), + (pCurrentStateMedium == pMedium) ? " (CURSTATE)" : ""); + + // find and print the snapshot that uses this particular medium (diff image) + FindAndPrintSnapshotUsingMedium(pMedium, pRootSnapshot, pCurrentSnapshot, uLevel, 0); + + // recurse into children + SafeIfaceArray<IMedium> aChildren; + CHECK_ERROR_BREAK(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(aChildren))); + for (uint32_t i = 0; + i < aChildren.size(); + ++i) + { + ComPtr<IMedium> pChild(aChildren[i]); + DumpMediumWithChildren(pCurrentStateMedium, pChild, pRootSnapshot, pCurrentSnapshot, uLevel + 1); + } + } while (0); +} + + +/** + * Handles the 'snapshot myvm list' sub-command. + * @returns Exit code. + * @param pArgs The handler argument package. + * @param pMachine Reference to the VM (locked) we're operating on. + */ +static RTEXITCODE handleSnapshotList(HandlerArg *pArgs, ComPtr<IMachine> &pMachine) +{ + static const RTGETOPTDEF g_aOptions[] = + { + { "--details", 'D', RTGETOPT_REQ_NOTHING }, + { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING }, + }; + + VMINFO_DETAILS enmDetails = VMINFO_STANDARD; + + int c; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, g_aOptions, RT_ELEMENTS(g_aOptions), 2 /*iArg*/, 0 /*fFlags*/); + while ((c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 'D': enmDetails = VMINFO_FULL; break; + case 'M': enmDetails = VMINFO_MACHINEREADABLE; break; + default: return errorGetOpt(c, &ValueUnion); + } + } + + ComPtr<ISnapshot> pSnapshot; + HRESULT hrc = pMachine->FindSnapshot(Bstr().raw(), pSnapshot.asOutParam()); + if (FAILED(hrc)) + { + RTPrintf(Snapshot::tr("This machine does not have any snapshots\n")); + return RTEXITCODE_FAILURE; + } + if (pSnapshot) + { + ComPtr<ISnapshot> pCurrentSnapshot; + CHECK_ERROR2I_RET(pMachine, COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam()), RTEXITCODE_FAILURE); + hrc = showSnapshots(pSnapshot, pCurrentSnapshot, enmDetails); + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + } + return RTEXITCODE_SUCCESS; +} + +/** + * Implementation for "VBoxManage snapshot ... dump". This goes thru the machine's + * medium attachments and calls DumpMediumWithChildren() for each hard disk medium found, + * which then dumps the parent/child tree of that medium together with the corresponding + * snapshots. + * @param pMachine Machine to dump snapshots for. + */ +void DumpSnapshot(ComPtr<IMachine> &pMachine) +{ + HRESULT hrc; + + do + { + // get root snapshot + ComPtr<ISnapshot> pSnapshot; + CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr("").raw(), pSnapshot.asOutParam())); + + // get current snapshot + ComPtr<ISnapshot> pCurrentSnapshot; + CHECK_ERROR_BREAK(pMachine, COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam())); + + // get media attachments + SafeIfaceArray<IMediumAttachment> aAttachments; + CHECK_ERROR_BREAK(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aAttachments))); + for (uint32_t i = 0; + i < aAttachments.size(); + ++i) + { + ComPtr<IMediumAttachment> pAttach(aAttachments[i]); + DeviceType_T type; + CHECK_ERROR_BREAK(pAttach, COMGETTER(Type)(&type)); + if (type == DeviceType_HardDisk) + { + ComPtr<IMedium> pCurrentStateMedium; + CHECK_ERROR_BREAK(pAttach, COMGETTER(Medium)(pCurrentStateMedium.asOutParam())); + + ComPtr<IMedium> pBaseMedium; + CHECK_ERROR_BREAK(pCurrentStateMedium, COMGETTER(Base)(pBaseMedium.asOutParam())); + + Bstr bstrBaseMediumName; + CHECK_ERROR_BREAK(pBaseMedium, COMGETTER(Name)(bstrBaseMediumName.asOutParam())); + + RTPrintf(Snapshot::tr("[%RI32] Images and snapshots for medium \"%ls\"\n"), i, bstrBaseMediumName.raw()); + + DumpMediumWithChildren(pCurrentStateMedium, + pBaseMedium, + pSnapshot, + pCurrentSnapshot, + 0); + } + } + } while (0); +} + +typedef enum SnapshotUniqueFlags +{ + SnapshotUniqueFlags_Null = 0, + SnapshotUniqueFlags_Number = RT_BIT(1), + SnapshotUniqueFlags_Timestamp = RT_BIT(2), + SnapshotUniqueFlags_Space = RT_BIT(16), + SnapshotUniqueFlags_Force = RT_BIT(30) +} SnapshotUniqueFlags; + +static int parseSnapshotUniqueFlags(const char *psz, SnapshotUniqueFlags *pUnique) +{ + int vrc = VINF_SUCCESS; + unsigned uUnique = 0; + while (psz && *psz && RT_SUCCESS(vrc)) + { + size_t len; + const char *pszComma = strchr(psz, ','); + if (pszComma) + len = pszComma - psz; + else + len = strlen(psz); + if (len > 0) + { + if (!RTStrNICmp(psz, "number", len)) + uUnique |= SnapshotUniqueFlags_Number; + else if (!RTStrNICmp(psz, "timestamp", len)) + uUnique |= SnapshotUniqueFlags_Timestamp; + else if (!RTStrNICmp(psz, "space", len)) + uUnique |= SnapshotUniqueFlags_Space; + else if (!RTStrNICmp(psz, "force", len)) + uUnique |= SnapshotUniqueFlags_Force; + else + vrc = VERR_PARSE_ERROR; + } + if (pszComma) + psz += len + 1; + else + psz += len; + } + + if (RT_SUCCESS(vrc)) + *pUnique = (SnapshotUniqueFlags)uUnique; + return vrc; +} + +/** + * Implementation for all VBoxManage snapshot ... subcommands. + * @param a + * @return + */ +RTEXITCODE handleSnapshot(HandlerArg *a) +{ + HRESULT hrc; + +/** @todo r=bird: sub-standard command line parsing here! + * + * 'VBoxManage snapshot empty take --help' takes a snapshot rather than display + * help as you would expect. + * + */ + + /* we need at least a VM and a command */ + if (a->argc < 2) + return errorSyntax(Snapshot::tr("Not enough parameters")); + + /* the first argument must be the VM */ + Bstr bstrMachine(a->argv[0]); + ComPtr<IMachine> pMachine; + CHECK_ERROR(a->virtualBox, FindMachine(bstrMachine.raw(), + pMachine.asOutParam())); + if (!pMachine) + return RTEXITCODE_FAILURE; + + /* we have to open a session for this task (new or shared) */ + CHECK_ERROR_RET(pMachine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + do + { + /* replace the (read-only) IMachine object by a writable one */ + ComPtr<IMachine> sessionMachine; + CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam())); + + /* switch based on the command */ + bool fDelete = false, + fRestore = false, + fRestoreCurrent = false; + + if (!strcmp(a->argv[1], "take")) + { + setCurrentSubcommand(HELP_SCOPE_SNAPSHOT_TAKE); + + /* there must be a name */ + if (a->argc < 3) + { + errorSyntax(Snapshot::tr("Missing snapshot name")); + hrc = E_FAIL; + break; + } + Bstr name(a->argv[2]); + + /* parse the optional arguments */ + Bstr desc; + bool fPause = true; /* default is NO live snapshot */ + SnapshotUniqueFlags enmUnique = SnapshotUniqueFlags_Null; + static const RTGETOPTDEF s_aTakeOptions[] = + { + { "--description", 'd', RTGETOPT_REQ_STRING }, + { "-description", 'd', RTGETOPT_REQ_STRING }, + { "-desc", 'd', RTGETOPT_REQ_STRING }, + { "--pause", 'p', RTGETOPT_REQ_NOTHING }, + { "--live", 'l', RTGETOPT_REQ_NOTHING }, + { "--uniquename", 'u', RTGETOPT_REQ_STRING } + }; + RTGETOPTSTATE GetOptState; + RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTakeOptions, RT_ELEMENTS(s_aTakeOptions), + 3, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + int ch; + RTGETOPTUNION Value; + int vrc; + while ( SUCCEEDED(hrc) + && (ch = RTGetOpt(&GetOptState, &Value))) + { + switch (ch) + { + case 'p': + fPause = true; + break; + + case 'l': + fPause = false; + break; + + case 'd': + desc = Value.psz; + break; + + case 'u': + vrc = parseSnapshotUniqueFlags(Value.psz, &enmUnique); + if (RT_FAILURE(vrc)) + return errorArgument(Snapshot::tr("Invalid unique name description '%s'"), Value.psz); + break; + + default: + errorGetOpt(ch, &Value); + hrc = E_FAIL; + break; + } + } + if (FAILED(hrc)) + break; + + if (enmUnique & (SnapshotUniqueFlags_Number | SnapshotUniqueFlags_Timestamp)) + { + ComPtr<ISnapshot> pSnapshot; + hrc = sessionMachine->FindSnapshot(name.raw(), + pSnapshot.asOutParam()); + if (SUCCEEDED(hrc) || (enmUnique & SnapshotUniqueFlags_Force)) + { + /* there is a duplicate, need to create a unique name */ + uint32_t count = 0; + RTTIMESPEC now; + + if (enmUnique & SnapshotUniqueFlags_Number) + { + if (enmUnique & SnapshotUniqueFlags_Force) + count = 1; + else + count = 2; + RTTimeSpecSetNano(&now, 0); /* Shut up MSC */ + } + else + RTTimeNow(&now); + + while (count < 500) + { + Utf8Str suffix; + if (enmUnique & SnapshotUniqueFlags_Number) + suffix = Utf8StrFmt("%u", count); + else + { + RTTIMESPEC nowplus = now; + RTTimeSpecAddSeconds(&nowplus, count); + RTTIME stamp; + RTTimeExplode(&stamp, &nowplus); + suffix = Utf8StrFmt("%04u-%02u-%02uT%02u:%02u:%02uZ", stamp.i32Year, stamp.u8Month, stamp.u8MonthDay, stamp.u8Hour, stamp.u8Minute, stamp.u8Second); + } + Bstr tryName = name; + if (enmUnique & SnapshotUniqueFlags_Space) + tryName = BstrFmt("%ls %s", name.raw(), suffix.c_str()); + else + tryName = BstrFmt("%ls%s", name.raw(), suffix.c_str()); + count++; + hrc = sessionMachine->FindSnapshot(tryName.raw(), + pSnapshot.asOutParam()); + if (FAILED(hrc)) + { + name = tryName; + break; + } + } + if (SUCCEEDED(hrc)) + { + errorArgument(Snapshot::tr("Failed to generate a unique snapshot name")); + hrc = E_FAIL; + break; + } + } + hrc = S_OK; + } + + ComPtr<IProgress> progress; + Bstr snapId; + CHECK_ERROR_BREAK(sessionMachine, TakeSnapshot(name.raw(), desc.raw(), + fPause, snapId.asOutParam(), + progress.asOutParam())); + + hrc = showProgress(progress); + if (SUCCEEDED(hrc)) + RTPrintf(Snapshot::tr("Snapshot taken. UUID: %ls\n"), snapId.raw()); + else + CHECK_PROGRESS_ERROR(progress, (Snapshot::tr("Failed to take snapshot"))); + } + else if ( (fDelete = !strcmp(a->argv[1], "delete")) + || (fRestore = !strcmp(a->argv[1], "restore")) + || (fRestoreCurrent = !strcmp(a->argv[1], "restorecurrent")) + ) + { + setCurrentSubcommand(fDelete ? HELP_SCOPE_SNAPSHOT_DELETE + : fRestore ? HELP_SCOPE_SNAPSHOT_RESTORE + : HELP_SCOPE_SNAPSHOT_RESTORECURRENT); + + if (fRestoreCurrent) + { + if (a->argc > 2) + { + errorSyntax(Snapshot::tr("Too many arguments")); + hrc = E_FAIL; + break; + } + } + /* exactly one parameter: snapshot name */ + else if (a->argc != 3) + { + errorSyntax(Snapshot::tr("Expecting snapshot name only")); + hrc = E_FAIL; + break; + } + + ComPtr<ISnapshot> pSnapshot; + + if (fRestoreCurrent) + { + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(CurrentSnapshot)(pSnapshot.asOutParam())); + if (pSnapshot.isNull()) + { + RTPrintf(Snapshot::tr("This machine does not have any snapshots\n")); + return RTEXITCODE_FAILURE; + } + } + else + { + // restore or delete snapshot: then resolve cmd line argument to snapshot instance + CHECK_ERROR_BREAK(sessionMachine, FindSnapshot(Bstr(a->argv[2]).raw(), + pSnapshot.asOutParam())); + } + + Bstr bstrSnapGuid; + CHECK_ERROR_BREAK(pSnapshot, COMGETTER(Id)(bstrSnapGuid.asOutParam())); + + Bstr bstrSnapName; + CHECK_ERROR_BREAK(pSnapshot, COMGETTER(Name)(bstrSnapName.asOutParam())); + + ComPtr<IProgress> pProgress; + + RTPrintf(Snapshot::tr("%s snapshot '%ls' (%ls)\n"), + fDelete ? Snapshot::tr("Deleting") : Snapshot::tr("Restoring"), bstrSnapName.raw(), bstrSnapGuid.raw()); + + if (fDelete) + { + CHECK_ERROR_BREAK(sessionMachine, DeleteSnapshot(bstrSnapGuid.raw(), + pProgress.asOutParam())); + } + else + { + // restore or restore current + CHECK_ERROR_BREAK(sessionMachine, RestoreSnapshot(pSnapshot, pProgress.asOutParam())); + } + + hrc = showProgress(pProgress); + CHECK_PROGRESS_ERROR(pProgress, (Snapshot::tr("Snapshot operation failed"))); + } + else if (!strcmp(a->argv[1], "edit")) + { + setCurrentSubcommand(HELP_SCOPE_SNAPSHOT_EDIT); + if (a->argc < 3) + { + errorSyntax(Snapshot::tr("Missing snapshot name")); + hrc = E_FAIL; + break; + } + + /* Parse the optional arguments, allowing more freedom than the + * synopsis explains. Can rename multiple snapshots and so on. */ + ComPtr<ISnapshot> pSnapshot; + static const RTGETOPTDEF s_aEditOptions[] = + { + { "--current", 'c', RTGETOPT_REQ_NOTHING }, + { "-current", 'c', RTGETOPT_REQ_NOTHING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "-name", 'n', RTGETOPT_REQ_STRING }, + { "-newname", 'n', RTGETOPT_REQ_STRING }, + { "--description", 'd', RTGETOPT_REQ_STRING }, + { "-description", 'd', RTGETOPT_REQ_STRING }, + { "-desc", 'd', RTGETOPT_REQ_STRING } + }; + RTGETOPTSTATE GetOptState; + RTGetOptInit(&GetOptState, a->argc, a->argv, s_aEditOptions, RT_ELEMENTS(s_aEditOptions), + 2, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + int ch; + RTGETOPTUNION Value; + while ( SUCCEEDED(hrc) + && (ch = RTGetOpt(&GetOptState, &Value))) + { + switch (ch) + { + case 'c': + CHECK_ERROR_BREAK(sessionMachine, COMGETTER(CurrentSnapshot)(pSnapshot.asOutParam())); + if (pSnapshot.isNull()) + { + RTPrintf(Snapshot::tr("This machine does not have any snapshots\n")); + return RTEXITCODE_FAILURE; + } + break; + + case 'n': + CHECK_ERROR_BREAK(pSnapshot, COMSETTER(Name)(Bstr(Value.psz).raw())); + break; + + case 'd': + CHECK_ERROR_BREAK(pSnapshot, COMSETTER(Description)(Bstr(Value.psz).raw())); + break; + + case VINF_GETOPT_NOT_OPTION: + CHECK_ERROR_BREAK(sessionMachine, FindSnapshot(Bstr(Value.psz).raw(), pSnapshot.asOutParam())); + break; + + default: + errorGetOpt(ch, &Value); + hrc = E_FAIL; + break; + } + } + + if (FAILED(hrc)) + break; + } + else if (!strcmp(a->argv[1], "showvminfo")) + { + setCurrentSubcommand(HELP_SCOPE_SNAPSHOT_SHOWVMINFO); + + /* exactly one parameter: snapshot name */ + if (a->argc != 3) + { + errorSyntax(Snapshot::tr("Expecting snapshot name only")); + hrc = E_FAIL; + break; + } + + ComPtr<ISnapshot> pSnapshot; + + CHECK_ERROR_BREAK(sessionMachine, FindSnapshot(Bstr(a->argv[2]).raw(), + pSnapshot.asOutParam())); + + /* get the machine of the given snapshot */ + ComPtr<IMachine> pMachine2; + pSnapshot->COMGETTER(Machine)(pMachine2.asOutParam()); + showVMInfo(a->virtualBox, pMachine2, NULL, VMINFO_NONE); + } + else if (!strcmp(a->argv[1], "list")) + { + setCurrentSubcommand(HELP_SCOPE_SNAPSHOT_LIST); + hrc = handleSnapshotList(a, sessionMachine) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL; + } + else if (!strcmp(a->argv[1], "dump")) // undocumented parameter to debug snapshot info + DumpSnapshot(sessionMachine); + else + { + errorSyntax(Snapshot::tr("Invalid parameter '%s'"), a->argv[1]); + hrc = E_FAIL; + } + } while (0); + + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp new file mode 100644 index 00000000..395196ad --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp @@ -0,0 +1,1306 @@ +/* $Id: VBoxManageStorageController.cpp $ */ +/** @file + * VBoxManage - The storage controller related commands. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include <iprt/path.h> +#include <iprt/param.h> +#include <iprt/string.h> +#include <iprt/ctype.h> +#include <iprt/stream.h> +#include <iprt/getopt.h> +#include <VBox/log.h> + +#include "VBoxManage.h" +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Storage); + +// funcs +/////////////////////////////////////////////////////////////////////////////// + + +static const RTGETOPTDEF g_aStorageAttachOptions[] = +{ + { "--storagectl", 's', RTGETOPT_REQ_STRING }, + { "--port", 'p', RTGETOPT_REQ_UINT32 }, + { "--device", 'd', RTGETOPT_REQ_UINT32 }, + { "--type", 't', RTGETOPT_REQ_STRING }, + { "--medium", 'm', RTGETOPT_REQ_STRING }, + { "--mtype", 'M', RTGETOPT_REQ_STRING }, + { "--passthrough", 'h', RTGETOPT_REQ_STRING }, + { "--tempeject", 'e', RTGETOPT_REQ_STRING }, + { "--nonrotational", 'n', RTGETOPT_REQ_STRING }, + { "--discard", 'u', RTGETOPT_REQ_STRING }, + { "--hotpluggable", 'o', RTGETOPT_REQ_STRING }, + { "--bandwidthgroup", 'b', RTGETOPT_REQ_STRING }, + { "--forceunmount", 'f', RTGETOPT_REQ_NOTHING }, + { "--comment", 'C', RTGETOPT_REQ_STRING }, + { "--setuuid", 'q', RTGETOPT_REQ_STRING }, + { "--setparentuuid", 'Q', RTGETOPT_REQ_STRING }, + // iSCSI options + { "--server", 'S', RTGETOPT_REQ_STRING }, + { "--target", 'T', RTGETOPT_REQ_STRING }, + { "--tport", 'P', RTGETOPT_REQ_STRING }, + { "--lun", 'L', RTGETOPT_REQ_STRING }, + { "--encodedlun", 'E', RTGETOPT_REQ_STRING }, + { "--username", 'U', RTGETOPT_REQ_STRING }, + { "--password", 'W', RTGETOPT_REQ_STRING }, + { "--passwordfile", 'w', RTGETOPT_REQ_STRING }, + { "--initiator", 'N', RTGETOPT_REQ_STRING }, + { "--intnet", 'I', RTGETOPT_REQ_NOTHING }, +}; + +RTEXITCODE handleStorageAttach(HandlerArg *a) +{ + int c = VERR_INTERNAL_ERROR; /* initialized to shut up gcc */ + HRESULT hrc = S_OK; + ULONG port = ~0U; + ULONG device = ~0U; + bool fForceUnmount = false; + bool fSetMediumType = false; + bool fSetNewUuid = false; + bool fSetNewParentUuid = false; + MediumType_T enmMediumType = MediumType_Normal; + Bstr bstrComment; + const char *pszCtl = NULL; + DeviceType_T devTypeRequested = DeviceType_Null; + const char *pszMedium = NULL; + const char *pszPassThrough = NULL; + const char *pszTempEject = NULL; + const char *pszNonRotational = NULL; + const char *pszDiscard = NULL; + const char *pszHotPluggable = NULL; + const char *pszBandwidthGroup = NULL; + Bstr bstrNewUuid; + Bstr bstrNewParentUuid; + // iSCSI options + Bstr bstrServer; + Bstr bstrTarget; + Bstr bstrPort; + Bstr bstrLun; + Bstr bstrUsername; + Bstr bstrPassword; + Bstr bstrInitiator; + Bstr bstrIso; + Utf8Str strIso; + bool fIntNet = false; + + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + ComPtr<IMachine> machine; + ComPtr<IStorageController> storageCtl; + ComPtr<ISystemProperties> systemProperties; + + RTGetOptInit(&GetState, a->argc, a->argv, g_aStorageAttachOptions, + RT_ELEMENTS(g_aStorageAttachOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + + while ( SUCCEEDED(hrc) + && (c = RTGetOpt(&GetState, &ValueUnion))) + { + switch (c) + { + case 's': // storage controller name + { + if (ValueUnion.psz) + pszCtl = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'p': // port + { + port = ValueUnion.u32; + break; + } + + case 'd': // device + { + device = ValueUnion.u32; + break; + } + + case 'm': // medium <none|emptydrive|additions|uuid|filename|host:<drive>|iSCSI> + { + if (ValueUnion.psz) + pszMedium = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 't': // type <dvddrive|hdd|fdd> + { + if (ValueUnion.psz) + { + if (!RTStrICmp(ValueUnion.psz, "hdd")) + devTypeRequested = DeviceType_HardDisk; + else if (!RTStrICmp(ValueUnion.psz, "fdd")) + devTypeRequested = DeviceType_Floppy; + else if (!RTStrICmp(ValueUnion.psz, "dvddrive")) + devTypeRequested = DeviceType_DVD; + else + return errorArgument(Storage::tr("Invalid --type argument '%s'"), ValueUnion.psz); + } + else + hrc = E_FAIL; + break; + } + + case 'h': // passthrough <on|off> + { + if (ValueUnion.psz) + pszPassThrough = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'e': // tempeject <on|off> + { + if (ValueUnion.psz) + pszTempEject = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'n': // nonrotational <on|off> + { + if (ValueUnion.psz) + pszNonRotational = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'u': // discard <on|off> + { + if (ValueUnion.psz) + pszDiscard = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'o': // hotpluggable <on|off> + { + if (ValueUnion.psz) + pszHotPluggable = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'b': // bandwidthgroup <name> + { + if (ValueUnion.psz) + pszBandwidthGroup = ValueUnion.psz; + else + hrc = E_FAIL; + break; + } + + case 'f': // force unmount medium during runtime + { + fForceUnmount = true; + break; + } + + case 'C': + if (ValueUnion.psz) + bstrComment = ValueUnion.psz; + else + hrc = E_FAIL; + break; + + case 'q': + if (ValueUnion.psz) + { + bstrNewUuid = ValueUnion.psz; + fSetNewUuid = true; + } + else + hrc = E_FAIL; + break; + + case 'Q': + if (ValueUnion.psz) + { + bstrNewParentUuid = ValueUnion.psz; + fSetNewParentUuid = true; + } + else + hrc = E_FAIL; + break; + + case 'S': // --server + bstrServer = ValueUnion.psz; + break; + + case 'T': // --target + bstrTarget = ValueUnion.psz; + break; + + case 'P': // --tport + bstrPort = ValueUnion.psz; + break; + + case 'L': // --lun + bstrLun = ValueUnion.psz; + break; + + case 'E': // --encodedlun + bstrLun = BstrFmt("enc%s", ValueUnion.psz); + break; + + case 'U': // --username + bstrUsername = ValueUnion.psz; + break; + + case 'W': // --password + bstrPassword = ValueUnion.psz; + break; + + case 'w': // --passwordFile + { + Utf8Str utf8Password; + RTEXITCODE rcExit = readPasswordFile(ValueUnion.psz, &utf8Password); + if (rcExit != RTEXITCODE_SUCCESS) + hrc = E_FAIL; + bstrPassword = utf8Password; + break; + } + case 'N': // --initiator + bstrInitiator = ValueUnion.psz; + break; + + case 'M': // --type + { + int vrc = parseMediumType(ValueUnion.psz, &enmMediumType); + if (RT_FAILURE(vrc)) + return errorArgument(Storage::tr("Invalid medium type '%s'"), ValueUnion.psz); + fSetMediumType = true; + break; + } + + case 'I': // --intnet + fIntNet = true; + break; + + default: + { + errorGetOpt(c, &ValueUnion); + hrc = E_FAIL; + break; + } + } + } + + if (FAILED(hrc)) + return RTEXITCODE_FAILURE; + + if (!pszCtl) + return errorSyntax(Storage::tr("Storage controller name not specified")); + + /* get the virtualbox system properties */ + CHECK_ERROR_RET(a->virtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam()), RTEXITCODE_FAILURE); + + // find the machine, lock it, get the mutable session machine + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + SessionType_T st; + CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), RTEXITCODE_FAILURE); + a->session->COMGETTER(Machine)(machine.asOutParam()); + + try + { + bool fRunTime = (st == SessionType_Shared); + + if (fRunTime) + { + if (pszPassThrough) + throw Utf8Str(Storage::tr("Drive passthrough state cannot be changed while the VM is running\n")); + else if (pszBandwidthGroup) + throw Utf8Str(Storage::tr("Bandwidth group cannot be changed while the VM is running\n")); + } + + /* check if the storage controller is present */ + hrc = machine->GetStorageControllerByName(Bstr(pszCtl).raw(), + storageCtl.asOutParam()); + if (FAILED(hrc)) + throw Utf8StrFmt(Storage::tr("Could not find a controller named '%s'\n"), pszCtl); + + StorageBus_T storageBus = StorageBus_Null; + CHECK_ERROR_RET(storageCtl, COMGETTER(Bus)(&storageBus), RTEXITCODE_FAILURE); + ULONG maxPorts = 0; + CHECK_ERROR_RET(systemProperties, GetMaxPortCountForStorageBus(storageBus, &maxPorts), RTEXITCODE_FAILURE); + ULONG maxDevices = 0; + CHECK_ERROR_RET(systemProperties, GetMaxDevicesPerPortForStorageBus(storageBus, &maxDevices), RTEXITCODE_FAILURE); + + if (port == ~0U) + { + if (maxPorts == 1) + port = 0; + else + return errorSyntax(Storage::tr("Port not specified")); + } + if (device == ~0U) + { + if (maxDevices == 1) + device = 0; + else + return errorSyntax(Storage::tr("Device not specified")); + } + + /* for sata controller check if the port count is big enough + * to accommodate the current port which is being assigned + * else just increase the port count + */ + { + ULONG ulPortCount = 0; + ULONG ulMaxPortCount = 0; + + CHECK_ERROR(storageCtl, COMGETTER(MaxPortCount)(&ulMaxPortCount)); + CHECK_ERROR(storageCtl, COMGETTER(PortCount)(&ulPortCount)); + + if ( (ulPortCount != ulMaxPortCount) + && (port >= ulPortCount) + && (port < ulMaxPortCount)) + CHECK_ERROR(storageCtl, COMSETTER(PortCount)(port + 1)); + } + + StorageControllerType_T ctlType = StorageControllerType_Null; + CHECK_ERROR(storageCtl, COMGETTER(ControllerType)(&ctlType)); + + if (!RTStrICmp(pszMedium, "none")) + { + CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl).raw(), port, device)); + } + else if (!RTStrICmp(pszMedium, "emptydrive")) + { + if (fRunTime) + { + ComPtr<IMediumAttachment> mediumAttachment; + DeviceType_T deviceType = DeviceType_Null; + hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port, device, + mediumAttachment.asOutParam()); + if (SUCCEEDED(hrc)) + { + mediumAttachment->COMGETTER(Type)(&deviceType); + + if ( (deviceType == DeviceType_DVD) + || (deviceType == DeviceType_Floppy)) + { + /* just unmount the floppy/dvd */ + CHECK_ERROR(machine, UnmountMedium(Bstr(pszCtl).raw(), + port, + device, + fForceUnmount)); + } + } + else if (devTypeRequested == DeviceType_DVD) + { + /* + * Try to attach an empty DVD drive as a hotplug operation. + * Main will complain if the controller doesn't support hotplugging. + */ + CHECK_ERROR(machine, AttachDeviceWithoutMedium(Bstr(pszCtl).raw(), port, device, + devTypeRequested)); + deviceType = DeviceType_DVD; /* To avoid the error message below. */ + } + + if ( FAILED(hrc) + || !( deviceType == DeviceType_DVD + || deviceType == DeviceType_Floppy) + ) + throw Utf8StrFmt(Storage::tr("No DVD/Floppy Drive attached to the controller '%s'" + "at the port: %u, device: %u"), pszCtl, port, device); + + } + else + { + DeviceType_T deviceType = DeviceType_Null; + com::SafeArray <DeviceType_T> saDeviceTypes; + ULONG driveCheck = 0; + + /* check if the device type is supported by the controller */ + CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes))); + for (size_t i = 0; i < saDeviceTypes.size(); ++ i) + { + if ( (saDeviceTypes[i] == DeviceType_DVD) + || (saDeviceTypes[i] == DeviceType_Floppy)) + driveCheck++; + } + + if (!driveCheck) + throw Utf8StrFmt(Storage::tr("The attachment is not supported by the storage controller '%s'"), pszCtl); + + if (storageBus == StorageBus_Floppy) + deviceType = DeviceType_Floppy; + else + deviceType = DeviceType_DVD; + + /* attach a empty floppy/dvd drive after removing previous attachment */ + machine->DetachDevice(Bstr(pszCtl).raw(), port, device); + CHECK_ERROR(machine, AttachDeviceWithoutMedium(Bstr(pszCtl).raw(), port, device, + deviceType)); + } + } // end if (!RTStrICmp(pszMedium, "emptydrive")) + else + { + ComPtr<IMedium> pMedium2Mount; + + // not "none", not "emptydrive": then it must be a UUID or filename or hostdrive or iSCSI; + // for all these we first need to know the type of drive we're attaching to + { + /* + * try to determine the type of the drive from the + * storage controller chipset, the attachment and + * the medium being attached + */ + if (ctlType == StorageControllerType_I82078) // floppy controller + devTypeRequested = DeviceType_Floppy; + else + { + /* + * for SATA/SCSI/IDE it is hard to tell if it is a harddisk or + * a dvd being attached so lets check if the medium attachment + * and the medium, both are of same type. if yes then we are + * sure of its type and don't need the user to enter it manually + * else ask the user for the type. + */ + ComPtr<IMediumAttachment> mediumAttachment; + hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, + mediumAttachment.asOutParam()); + if (SUCCEEDED(hrc)) + { + DeviceType_T deviceType; + mediumAttachment->COMGETTER(Type)(&deviceType); + + if (pszMedium) + { + if (!RTStrICmp(pszMedium, "additions")) + { + ComPtr<ISystemProperties> pProperties; + CHECK_ERROR(a->virtualBox, + COMGETTER(SystemProperties)(pProperties.asOutParam())); + CHECK_ERROR(pProperties, COMGETTER(DefaultAdditionsISO)(bstrIso.asOutParam())); + strIso = Utf8Str(bstrIso); + if (strIso.isEmpty()) + throw Utf8Str(Storage::tr("Cannot find the Guest Additions ISO image\n")); + pszMedium = strIso.c_str(); + if (devTypeRequested == DeviceType_Null) + devTypeRequested = DeviceType_DVD; + } + ComPtr<IMedium> pExistingMedium; + hrc = openMedium(a, pszMedium, deviceType, + AccessMode_ReadWrite, + pExistingMedium, + false /* fForceNewUuidOnOpen */, + true /* fSilent */); + if (SUCCEEDED(hrc) && pExistingMedium) + { + if ( (deviceType == DeviceType_DVD) + || (deviceType == DeviceType_HardDisk) + ) + devTypeRequested = deviceType; + } + } + else + devTypeRequested = deviceType; + } + } + } + + if (devTypeRequested == DeviceType_Null) // still the initializer value? + throw Utf8Str(Storage::tr("Argument --type must be specified\n")); + + /* check if the device type is supported by the controller */ + { + com::SafeArray <DeviceType_T> saDeviceTypes; + + CHECK_ERROR(systemProperties, GetDeviceTypesForStorageBus(storageBus, ComSafeArrayAsOutParam(saDeviceTypes))); + if (SUCCEEDED(hrc)) + { + ULONG driveCheck = 0; + for (size_t i = 0; i < saDeviceTypes.size(); ++ i) + if (saDeviceTypes[i] == devTypeRequested) + driveCheck++; + if (!driveCheck) + throw Utf8StrFmt(Storage::tr("The given attachment is not supported by the storage controller '%s'"), pszCtl); + } + else + goto leave; + } + + // find the medium given + /* host drive? */ + if (!RTStrNICmp(pszMedium, RT_STR_TUPLE("host:"))) + { + ComPtr<IHost> host; + CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam())); + + if (devTypeRequested == DeviceType_DVD) + { + hrc = host->FindHostDVDDrive(Bstr(pszMedium + 5).raw(), + pMedium2Mount.asOutParam()); + if (!pMedium2Mount) + { + /* 2nd try: try with the real name, important on Linux+libhal */ + char szPathReal[RTPATH_MAX]; + if (RT_FAILURE(RTPathReal(pszMedium + 5, szPathReal, sizeof(szPathReal)))) + throw Utf8StrFmt(Storage::tr("Invalid host DVD drive name \"%s\""), pszMedium + 5); + hrc = host->FindHostDVDDrive(Bstr(szPathReal).raw(), + pMedium2Mount.asOutParam()); + if (!pMedium2Mount) + throw Utf8StrFmt(Storage::tr("Invalid host DVD drive name \"%s\""), pszMedium + 5); + } + } + else + { + // floppy + hrc = host->FindHostFloppyDrive(Bstr(pszMedium + 5).raw(), + pMedium2Mount.asOutParam()); + if (!pMedium2Mount) + throw Utf8StrFmt(Storage::tr("Invalid host floppy drive name \"%s\""), pszMedium + 5); + } + } + else if (!RTStrICmp(pszMedium, "iSCSI")) + { + /* check for required options */ + if (bstrServer.isEmpty() || bstrTarget.isEmpty()) + throw Utf8StrFmt(Storage::tr("Parameters --server and --target are required for iSCSI media")); + + /** @todo move the location stuff to Main, which can use pfnComposeName + * from the disk backends to construct the location properly. Also do + * not use slashes to separate the parts, as otherwise only the last + * element containing information will be shown. */ + Bstr bstrISCSIMedium; + if ( bstrLun.isEmpty() + || (bstrLun == "0") + || (bstrLun == "enc0") + ) + bstrISCSIMedium = BstrFmt("%ls|%ls", bstrServer.raw(), bstrTarget.raw()); + else + bstrISCSIMedium = BstrFmt("%ls|%ls|%ls", bstrServer.raw(), bstrTarget.raw(), bstrLun.raw()); + + CHECK_ERROR(a->virtualBox, CreateMedium(Bstr("iSCSI").raw(), + bstrISCSIMedium.raw(), + AccessMode_ReadWrite, + DeviceType_HardDisk, + pMedium2Mount.asOutParam())); + if (FAILED(hrc)) goto leave; /** @todo r=andy Argh!! Why not using exceptions here? */ + if (!bstrPort.isEmpty()) + bstrServer = BstrFmt("%ls:%ls", bstrServer.raw(), bstrPort.raw()); + + // set the other iSCSI parameters as properties + com::SafeArray <BSTR> names; + com::SafeArray <BSTR> values; + Bstr("TargetAddress").detachTo(names.appendedRaw()); + bstrServer.detachTo(values.appendedRaw()); + Bstr("TargetName").detachTo(names.appendedRaw()); + bstrTarget.detachTo(values.appendedRaw()); + + if (!bstrLun.isEmpty()) + { + Bstr("LUN").detachTo(names.appendedRaw()); + bstrLun.detachTo(values.appendedRaw()); + } + if (!bstrUsername.isEmpty()) + { + Bstr("InitiatorUsername").detachTo(names.appendedRaw()); + bstrUsername.detachTo(values.appendedRaw()); + } + if (!bstrPassword.isEmpty()) + { + Bstr("InitiatorSecret").detachTo(names.appendedRaw()); + bstrPassword.detachTo(values.appendedRaw()); + } + if (!bstrInitiator.isEmpty()) + { + Bstr("InitiatorName").detachTo(names.appendedRaw()); + bstrInitiator.detachTo(values.appendedRaw()); + } + + /// @todo add --targetName and --targetPassword options + + if (fIntNet) + { + Bstr("HostIPStack").detachTo(names.appendedRaw()); + Bstr("0").detachTo(values.appendedRaw()); + } + + CHECK_ERROR(pMedium2Mount, SetProperties(ComSafeArrayAsInParam(names), + ComSafeArrayAsInParam(values))); + if (FAILED(hrc)) goto leave; + Bstr guid; + CHECK_ERROR(pMedium2Mount, COMGETTER(Id)(guid.asOutParam())); + if (FAILED(hrc)) goto leave; + RTPrintf(Storage::tr("iSCSI disk created. UUID: %s\n"), Utf8Str(guid).c_str()); + } + else + { + if (!pszMedium) + { + ComPtr<IMediumAttachment> mediumAttachment; + hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, + mediumAttachment.asOutParam()); + if (FAILED(hrc)) + throw Utf8Str(Storage::tr("Missing --medium argument")); + } + else + { + Bstr bstrMedium(pszMedium); + hrc = openMedium(a, pszMedium, devTypeRequested, + AccessMode_ReadWrite, pMedium2Mount, + fSetNewUuid, false /* fSilent */); + if (FAILED(hrc) || !pMedium2Mount) + throw Utf8StrFmt(Storage::tr("Invalid UUID or filename \"%s\""), pszMedium); + } + } + + // set medium/parent medium UUID, if so desired + if (pMedium2Mount && (fSetNewUuid || fSetNewParentUuid)) + { + CHECK_ERROR(pMedium2Mount, SetIds(fSetNewUuid, bstrNewUuid.raw(), + fSetNewParentUuid, bstrNewParentUuid.raw())); + if (FAILED(hrc)) + throw Utf8Str(Storage::tr("Failed to set the medium/parent medium UUID")); + } + + // set medium type, if so desired + if (pMedium2Mount && fSetMediumType) + { + MediumType_T enmMediumTypeOld; + CHECK_ERROR(pMedium2Mount, COMGETTER(Type)(&enmMediumTypeOld)); + if (SUCCEEDED(hrc)) + { + if (enmMediumTypeOld != enmMediumType) + { + CHECK_ERROR(pMedium2Mount, COMSETTER(Type)(enmMediumType)); + if (FAILED(hrc)) + throw Utf8Str(Storage::tr("Failed to set the medium type")); + } + } + } + + if (pMedium2Mount && !bstrComment.isEmpty()) + { + CHECK_ERROR(pMedium2Mount, COMSETTER(Description)(bstrComment.raw())); + } + + if (pszMedium) + { + switch (devTypeRequested) + { + case DeviceType_DVD: + case DeviceType_Floppy: + { + if (!fRunTime) + { + ComPtr<IMediumAttachment> mediumAttachment; + // check if there is a dvd/floppy drive at the given location, if not attach one first + hrc = machine->GetMediumAttachment(Bstr(pszCtl).raw(), + port, + device, + mediumAttachment.asOutParam()); + if (SUCCEEDED(hrc)) + { + DeviceType_T deviceType; + mediumAttachment->COMGETTER(Type)(&deviceType); + if (deviceType != devTypeRequested) + { + machine->DetachDevice(Bstr(pszCtl).raw(), port, device); + hrc = machine->AttachDeviceWithoutMedium(Bstr(pszCtl).raw(), + port, + device, + devTypeRequested); // DeviceType_DVD or DeviceType_Floppy + } + } + else + { + hrc = machine->AttachDeviceWithoutMedium(Bstr(pszCtl).raw(), + port, + device, + devTypeRequested); // DeviceType_DVD or DeviceType_Floppy + } + } + + if (pMedium2Mount) + { + CHECK_ERROR(machine, MountMedium(Bstr(pszCtl).raw(), + port, + device, + pMedium2Mount, + fForceUnmount)); + } + break; + } // end DeviceType_DVD or DeviceType_Floppy: + + case DeviceType_HardDisk: + { + // if there is anything attached at the given location, remove it + machine->DetachDevice(Bstr(pszCtl).raw(), port, device); + CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl).raw(), + port, + device, + DeviceType_HardDisk, + pMedium2Mount)); + break; + } + + default: break; /* Shut up MSC */ + } + } + } + + if ( pszPassThrough + && (SUCCEEDED(hrc))) + { + ComPtr<IMediumAttachment> mattach; + CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, mattach.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszPassThrough, "on")) + { + CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl).raw(), + port, device, TRUE)); + } + else if (!RTStrICmp(pszPassThrough, "off")) + { + CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl).raw(), + port, device, FALSE)); + } + else + throw Utf8StrFmt(Storage::tr("Invalid --passthrough argument '%s'"), pszPassThrough); + } + else + throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl); + } + + if ( pszTempEject + && (SUCCEEDED(hrc))) + { + ComPtr<IMediumAttachment> mattach; + CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, mattach.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszTempEject, "on")) + { + CHECK_ERROR(machine, TemporaryEjectDevice(Bstr(pszCtl).raw(), + port, device, TRUE)); + } + else if (!RTStrICmp(pszTempEject, "off")) + { + CHECK_ERROR(machine, TemporaryEjectDevice(Bstr(pszCtl).raw(), + port, device, FALSE)); + } + else + throw Utf8StrFmt(Storage::tr("Invalid --tempeject argument '%s'"), pszTempEject); + } + else + throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl); + } + + if ( pszNonRotational + && (SUCCEEDED(hrc))) + { + ComPtr<IMediumAttachment> mattach; + CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, mattach.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszNonRotational, "on")) + { + CHECK_ERROR(machine, NonRotationalDevice(Bstr(pszCtl).raw(), + port, device, TRUE)); + } + else if (!RTStrICmp(pszNonRotational, "off")) + { + CHECK_ERROR(machine, NonRotationalDevice(Bstr(pszCtl).raw(), + port, device, FALSE)); + } + else + throw Utf8StrFmt(Storage::tr("Invalid --nonrotational argument '%s'"), pszNonRotational); + } + else + throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl); + } + + if ( pszDiscard + && (SUCCEEDED(hrc))) + { + ComPtr<IMediumAttachment> mattach; + CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, mattach.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszDiscard, "on")) + { + CHECK_ERROR(machine, SetAutoDiscardForDevice(Bstr(pszCtl).raw(), + port, device, TRUE)); + } + else if (!RTStrICmp(pszDiscard, "off")) + { + CHECK_ERROR(machine, SetAutoDiscardForDevice(Bstr(pszCtl).raw(), + port, device, FALSE)); + } + else + throw Utf8StrFmt(Storage::tr("Invalid --discard argument '%s'"), pszDiscard); + } + else + throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl); + } + + if ( pszHotPluggable + && (SUCCEEDED(hrc))) + { + ComPtr<IMediumAttachment> mattach; + CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl).raw(), port, + device, mattach.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszHotPluggable, "on")) + { + CHECK_ERROR(machine, SetHotPluggableForDevice(Bstr(pszCtl).raw(), + port, device, TRUE)); + } + else if (!RTStrICmp(pszHotPluggable, "off")) + { + CHECK_ERROR(machine, SetHotPluggableForDevice(Bstr(pszCtl).raw(), + port, device, FALSE)); + } + else + throw Utf8StrFmt(Storage::tr("Invalid --hotpluggable argument '%s'"), pszHotPluggable); + } + else + throw Utf8StrFmt(Storage::tr("Couldn't find the controller attachment for the controller '%s'\n"), pszCtl); + } + + if ( pszBandwidthGroup + && !fRunTime + && SUCCEEDED(hrc)) + { + + if (!RTStrICmp(pszBandwidthGroup, "none")) + { + /* Just remove the bandwidth gorup. */ + CHECK_ERROR(machine, SetNoBandwidthGroupForDevice(Bstr(pszCtl).raw(), + port, device)); + } + else + { + ComPtr<IBandwidthControl> bwCtrl; + ComPtr<IBandwidthGroup> bwGroup; + + CHECK_ERROR(machine, COMGETTER(BandwidthControl)(bwCtrl.asOutParam())); + + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(bwCtrl, GetBandwidthGroup(Bstr(pszBandwidthGroup).raw(), bwGroup.asOutParam())); + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(machine, SetBandwidthGroupForDevice(Bstr(pszCtl).raw(), + port, device, bwGroup)); + } + } + } + } + + /* commit changes */ + if (SUCCEEDED(hrc)) + CHECK_ERROR(machine, SaveSettings()); + } + catch (const Utf8Str &strError) + { + errorArgument("%s", strError.c_str()); + hrc = E_FAIL; + } + + // machine must always be unlocked, even on errors +leave: + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + + +static const RTGETOPTDEF g_aStorageControllerOptions[] = +{ + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--add", 'a', RTGETOPT_REQ_STRING }, + { "--controller", 'c', RTGETOPT_REQ_STRING }, + { "--portcount", 'p', RTGETOPT_REQ_UINT32 }, + { "--remove", 'r', RTGETOPT_REQ_NOTHING }, + { "--rename", 'R', RTGETOPT_REQ_STRING }, + { "--hostiocache", 'i', RTGETOPT_REQ_STRING }, + { "--bootable", 'b', RTGETOPT_REQ_STRING }, +}; + +RTEXITCODE handleStorageController(HandlerArg *a) +{ + int c; + const char *pszCtl = NULL; + const char *pszBusType = NULL; + const char *pszCtlType = NULL; + const char *pszHostIOCache = NULL; + const char *pszBootable = NULL; + const char *pszCtlNewName = NULL; + ULONG portcount = ~0U; + bool fRemoveCtl = false; + ComPtr<IMachine> machine; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + + if (a->argc < 4) + return errorSyntax(Storage::tr("Too few parameters")); + + RTGetOptInit (&GetState, a->argc, a->argv, g_aStorageControllerOptions, + RT_ELEMENTS(g_aStorageControllerOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS); + + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'n': // controller name + Assert(ValueUnion.psz); + pszCtl = ValueUnion.psz; + break; + + case 'a': // controller bus type <ide/sata/scsi/floppy> + Assert(ValueUnion.psz); + pszBusType = ValueUnion.psz; + break; + + case 'c': // controller <lsilogic/buslogic/intelahci/piix3/piix4/ich6/i82078> + Assert(ValueUnion.psz); + pszCtlType = ValueUnion.psz; + break; + + case 'p': // portcount + portcount = ValueUnion.u32; + break; + + case 'r': // remove controller + fRemoveCtl = true; + break; + + case 'R': // rename controller + Assert(ValueUnion.psz); + pszCtlNewName = ValueUnion.psz; + break; + + case 'i': + pszHostIOCache = ValueUnion.psz; + break; + + case 'b': + pszBootable = ValueUnion.psz; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + HRESULT hrc; + + /* try to find the given machine */ + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(), + machine.asOutParam()), RTEXITCODE_FAILURE); + + /* open a session for the VM */ + CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), RTEXITCODE_FAILURE); + + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(machine.asOutParam()); + + if (!pszCtl) + { + /* it's important to always close sessions */ + a->session->UnlockMachine(); + return errorSyntax(Storage::tr("Storage controller name not specified\n")); + } + + if (fRemoveCtl) + { + CHECK_ERROR(machine, RemoveStorageController(Bstr(pszCtl).raw())); + } + else + { + if (pszBusType) + { + ComPtr<IStorageController> ctl; + + if (!RTStrICmp(pszBusType, "ide")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_IDE, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "sata")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_SATA, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "scsi")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_SCSI, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "floppy")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_Floppy, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "sas")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_SAS, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "usb")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_USB, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "pcie")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_PCIe, + ctl.asOutParam())); + } + else if (!RTStrICmp(pszBusType, "virtio-scsi") || !RTStrICmp(pszBusType, "virtio")) + { + CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl).raw(), + StorageBus_VirtioSCSI, + ctl.asOutParam())); + } + else + { + errorArgument(Storage::tr("Invalid --add argument '%s'"), pszBusType); + hrc = E_FAIL; + } + } + + if ( pszCtlType + && SUCCEEDED(hrc)) + { + ComPtr<IStorageController> ctl; + + CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(), + ctl.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszCtlType, "lsilogic")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic)); + } + else if (!RTStrICmp(pszCtlType, "buslogic")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic)); + } + else if (!RTStrICmp(pszCtlType, "intelahci")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci)); + } + else if (!RTStrICmp(pszCtlType, "piix3")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX3)); + } + else if (!RTStrICmp(pszCtlType, "piix4")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX4)); + } + else if (!RTStrICmp(pszCtlType, "ich6")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_ICH6)); + } + else if (!RTStrICmp(pszCtlType, "i82078")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_I82078)); + } + else if (!RTStrICmp(pszCtlType, "lsilogicsas")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogicSas)); + } + else if (!RTStrICmp(pszCtlType, "usb")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_USB)); + } + else if (!RTStrICmp(pszCtlType, "nvme")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_NVMe)); + } + else if (!RTStrICmp(pszCtlType, "virtio-scsi") || !RTStrICmp(pszCtlType, "virtio")) + { + CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_VirtioSCSI)); + } + else + { + errorArgument(Storage::tr("Invalid --type argument '%s'"), pszCtlType); + hrc = E_FAIL; + } + } + else + { + errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl); + hrc = E_FAIL; + } + } + + if ( (portcount != ~0U) + && SUCCEEDED(hrc)) + { + ComPtr<IStorageController> ctl; + + CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(), + ctl.asOutParam())); + + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(ctl, COMSETTER(PortCount)(portcount)); + } + else + { + errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl); + hrc = E_FAIL; /** @todo r=andy Overwrites original hrc. */ + } + } + + if ( pszHostIOCache + && SUCCEEDED(hrc)) + { + ComPtr<IStorageController> ctl; + + CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(), + ctl.asOutParam())); + + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszHostIOCache, "on")) + { + CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(TRUE)); + } + else if (!RTStrICmp(pszHostIOCache, "off")) + { + CHECK_ERROR(ctl, COMSETTER(UseHostIOCache)(FALSE)); + } + else + { + errorArgument(Storage::tr("Invalid --hostiocache argument '%s'"), pszHostIOCache); + hrc = E_FAIL; + } + } + else + { + errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl); + hrc = E_FAIL; /** @todo r=andy Ditto. */ + } + } + + if ( pszBootable + && SUCCEEDED(hrc)) + { + if (SUCCEEDED(hrc)) + { + if (!RTStrICmp(pszBootable, "on")) + { + CHECK_ERROR(machine, SetStorageControllerBootable(Bstr(pszCtl).raw(), TRUE)); + } + else if (!RTStrICmp(pszBootable, "off")) + { + CHECK_ERROR(machine, SetStorageControllerBootable(Bstr(pszCtl).raw(), FALSE)); + } + else + { + errorArgument(Storage::tr("Invalid --bootable argument '%s'"), pszBootable); + hrc = E_FAIL; + } + } + else + { + errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl); + hrc = E_FAIL; + } + } + + if ( pszCtlNewName + && SUCCEEDED(hrc)) + { + ComPtr<IStorageController> ctl; + + CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl).raw(), + ctl.asOutParam())); + + if (SUCCEEDED(hrc)) + { + CHECK_ERROR(ctl, COMSETTER(Name)(Bstr(pszCtlNewName).raw())); + } + else + { + errorArgument(Storage::tr("Couldn't find the controller with the name: '%s'\n"), pszCtl); + hrc = E_FAIL; + } + } + + } + + /* commit changes */ + if (SUCCEEDED(hrc)) + CHECK_ERROR(machine, SaveSettings()); + + /* it's important to always close sessions */ + a->session->UnlockMachine(); + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp new file mode 100644 index 00000000..f86a02c9 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp @@ -0,0 +1,581 @@ +/* $Id: VBoxManageUSB.cpp $ */ +/** @file + * VBoxManage - VirtualBox's command-line interface. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include <VBox/com/com.h> +#include <VBox/com/string.h> +#include <VBox/com/Guid.h> +#include <VBox/com/array.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> + +#include "VBoxManage.h" + +#include <iprt/asm.h> + +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Usb); + +/** + * Quick IUSBDevice implementation for detaching / attaching + * devices to the USB Controller. + */ +class MyUSBDevice : public IUSBDevice +{ +public: + // public initializer/uninitializer for internal purposes only + MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment) + : m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId), + m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash), + m_bstrComment(a_pszComment), + m_cRefs(0) + { + } + virtual ~MyUSBDevice() {} + + STDMETHOD_(ULONG, AddRef)(void) + { + return ASMAtomicIncU32(&m_cRefs); + } + STDMETHOD_(ULONG, Release)(void) + { + ULONG cRefs = ASMAtomicDecU32(&m_cRefs); + if (!cRefs) + delete this; + return cRefs; + } + STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject) + { + Guid guid(iid); + if (guid == Guid(COM_IIDOF(IUnknown))) + *ppvObject = (IUnknown *)this; +#ifdef RT_OS_WINDOWS + else if (guid == Guid(COM_IIDOF(IDispatch))) + *ppvObject = (IDispatch *)this; +#endif + else if (guid == Guid(COM_IIDOF(IUSBDevice))) + *ppvObject = (IUSBDevice *)this; + else + return E_NOINTERFACE; + AddRef(); + return S_OK; + } + + STDMETHOD(COMGETTER(Id))(OUT_GUID a_pId) { NOREF(a_pId); return E_NOTIMPL; } + STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId) { *a_pusVendorId = m_usVendorId; return S_OK; } + STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId) { *a_pusProductId = m_usProductId; return S_OK; } + STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision) { *a_pusRevision = m_bcdRevision; return S_OK; } + STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash; return S_OK; } + STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer) { NOREF(a_pManufacturer); return E_NOTIMPL; } + STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct) { NOREF(a_pProduct); return E_NOTIMPL; } + STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber) { NOREF(a_pSerialNumber); return E_NOTIMPL; } + STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress) { NOREF(a_pAddress); return E_NOTIMPL; } + +private: + /** The vendor id of this USB device. */ + USHORT m_usVendorId; + /** The product id of this USB device. */ + USHORT m_usProductId; + /** The product revision number of this USB device. + * (high byte = integer; low byte = decimal) */ + USHORT m_bcdRevision; + /** The USB serial hash of the device. */ + uint64_t m_u64SerialHash; + /** The user comment string. */ + Bstr m_bstrComment; + /** Reference counter. */ + uint32_t volatile m_cRefs; +}; + + +// types +/////////////////////////////////////////////////////////////////////////////// + +template <typename T> +class Nullable +{ +public: + + Nullable() : mIsNull(true) {} + Nullable(const T &aValue, bool aIsNull = false) + : mIsNull(aIsNull), mValue(aValue) {} + + bool isNull() const { return mIsNull; }; + void setNull(bool aIsNull = true) { mIsNull = aIsNull; } + + operator const T&() const { return mValue; } + + Nullable &operator= (const T &aValue) + { + mValue = aValue; + mIsNull = false; + return *this; + } + +private: + + bool mIsNull; + T mValue; +}; + +/** helper structure to encapsulate USB filter manipulation commands */ +struct USBFilterCmd +{ + struct USBFilter + { + USBFilter() + : mAction(USBDeviceFilterAction_Null) + {} + + Bstr mName; + Nullable <bool> mActive; + Bstr mVendorId; + Bstr mProductId; + Bstr mRevision; + Bstr mManufacturer; + Bstr mProduct; + Bstr mPort; + Bstr mRemote; + Bstr mSerialNumber; + Nullable <ULONG> mMaskedInterfaces; + USBDeviceFilterAction_T mAction; + }; + + enum Action { Invalid, Add, Modify, Remove }; + + USBFilterCmd() : mAction(Invalid), mIndex(0), mGlobal(false) {} + + Action mAction; + uint32_t mIndex; + /** flag whether the command target is a global filter */ + bool mGlobal; + /** machine this command is targeted at (null for global filters) */ + ComPtr<IMachine> mMachine; + USBFilter mFilter; +}; + +RTEXITCODE handleUSBFilter(HandlerArg *a) +{ + HRESULT hrc = S_OK; + USBFilterCmd cmd; + + /* which command? */ + cmd.mAction = USBFilterCmd::Invalid; + if (!strcmp(a->argv[0], "add")) + { + cmd.mAction = USBFilterCmd::Add; + setCurrentSubcommand(HELP_SCOPE_USBFILTER_ADD); + } + else if (!strcmp(a->argv[0], "modify")) + { + cmd.mAction = USBFilterCmd::Modify; + setCurrentSubcommand(HELP_SCOPE_USBFILTER_MODIFY); + } + else if (!strcmp(a->argv[0], "remove")) + { + cmd.mAction = USBFilterCmd::Remove; + setCurrentSubcommand(HELP_SCOPE_USBFILTER_REMOVE); + } + + if (cmd.mAction == USBFilterCmd::Invalid) + return errorUnknownSubcommand(a->argv[0]); + + /* which index? */ + if (VINF_SUCCESS != RTStrToUInt32Full(a->argv[1], 10, &cmd.mIndex)) + return errorSyntax(Usb::tr("Invalid index '%s'"), a->argv[1]); + + if (cmd.mAction == USBFilterCmd::Add || cmd.mAction == USBFilterCmd::Modify) + { + // set Active to true by default + // (assuming that the user sets up all necessary attributes + // at once and wants the filter to be active immediately) + if (cmd.mAction == USBFilterCmd::Add) + cmd.mFilter.mActive = true; + + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--target", 't', RTGETOPT_REQ_STRING }, + { "--name", 'n', RTGETOPT_REQ_STRING }, + { "--active", 'a', RTGETOPT_REQ_STRING }, + { "--vendorid", 'v', RTGETOPT_REQ_STRING }, + { "--productid", 'p', RTGETOPT_REQ_STRING }, + { "--revision", 'r', RTGETOPT_REQ_STRING }, + { "--manufacturer", 'm', RTGETOPT_REQ_STRING }, + { "--product", 'P', RTGETOPT_REQ_STRING }, + { "--serialnumber", 's', RTGETOPT_REQ_STRING }, + { "--port", 'o', RTGETOPT_REQ_STRING }, + { "--remote", 'R', RTGETOPT_REQ_STRING }, + { "--maskedinterfaces", 'M', RTGETOPT_REQ_UINT32 }, + { "--action", 'A', RTGETOPT_REQ_STRING } + }; + + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 't': // --target + if (!strcmp(ValueUnion.psz, "global")) + cmd.mGlobal = true; + else + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(ValueUnion.psz).raw(), + cmd.mMachine.asOutParam()), RTEXITCODE_FAILURE); + break; + case 'n': // --name + cmd.mFilter.mName = ValueUnion.psz; + break; + case 'a': // --active + if (!strcmp(ValueUnion.psz, "yes")) + cmd.mFilter.mActive = true; + else if (!strcmp(ValueUnion.psz, "no")) + cmd.mFilter.mActive = false; + else + return errorArgument(Usb::tr("Invalid --active argument '%s'"), ValueUnion.psz); + break; + case 'v': // --vendorid + cmd.mFilter.mVendorId = ValueUnion.psz; + break; + case 'p': // --productid + cmd.mFilter.mProductId = ValueUnion.psz; + break; + case 'r': // --revision + cmd.mFilter.mRevision = ValueUnion.psz; + break; + case 'm': // --manufacturer + cmd.mFilter.mManufacturer = ValueUnion.psz; + break; + case 'P': // --product + cmd.mFilter.mProduct = ValueUnion.psz; + break; + case 's': // --serialnumber + cmd.mFilter.mSerialNumber = ValueUnion.psz; + break; + case 'o': // --port + cmd.mFilter.mPort = ValueUnion.psz; + break; + case 'R': // --remote + cmd.mFilter.mRemote = ValueUnion.psz; + break; + case 'M': // --maskedinterfaces + cmd.mFilter.mMaskedInterfaces = ValueUnion.u32; + break; + case 'A': // --action + if (!strcmp(ValueUnion.psz, "ignore")) + cmd.mFilter.mAction = USBDeviceFilterAction_Ignore; + else if (!strcmp(ValueUnion.psz, "hold")) + cmd.mFilter.mAction = USBDeviceFilterAction_Hold; + else + return errorArgument(Usb::tr("Invalid USB filter action '%s'"), ValueUnion.psz); + break; + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + + // mandatory/forbidden options + if (!cmd.mGlobal && !cmd.mMachine) + return errorSyntax(Usb::tr("Missing required option: --target")); + + if (cmd.mAction == USBFilterCmd::Add) + { + if (cmd.mFilter.mName.isEmpty()) + return errorSyntax(Usb::tr("Missing required option: --name")); + + if (cmd.mGlobal && cmd.mFilter.mAction == USBDeviceFilterAction_Null) + return errorSyntax(Usb::tr("Missing required option: --action")); + + if (cmd.mGlobal && !cmd.mFilter.mRemote.isEmpty()) + return errorSyntax(Usb::tr("Option --remote applies to VM filters only (--target=<uuid|vmname>)")); + } + } + else if (cmd.mAction == USBFilterCmd::Remove) + { + RTGETOPTSTATE GetState; + RTGETOPTUNION ValueUnion; + static const RTGETOPTDEF s_aOptions[] = + { + { "--target", 't', RTGETOPT_REQ_STRING } + }; + int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); + AssertRCReturn(vrc, RTEXITCODE_FAILURE); + + while ((vrc = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (vrc) + { + case 't': // --target + if (!strcmp(ValueUnion.psz, "global")) + cmd.mGlobal = true; + else + CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(ValueUnion.psz).raw(), + cmd.mMachine.asOutParam()), RTEXITCODE_FAILURE); + break; + default: + return errorGetOpt(vrc, &ValueUnion); + } + } + // mandatory options + if (!cmd.mGlobal && !cmd.mMachine) + return errorSyntax(Usb::tr("Missing required option: --target")); + } + + USBFilterCmd::USBFilter &f = cmd.mFilter; + + ComPtr<IHost> host; + ComPtr<IUSBDeviceFilters> flts; + if (cmd.mGlobal) + CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE); + else + { + /* open a session for the VM */ + CHECK_ERROR_RET(cmd.mMachine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE); + /* get the mutable session machine */ + a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam()); + /* and get the USB device filters */ + CHECK_ERROR_RET(cmd.mMachine, COMGETTER(USBDeviceFilters)(flts.asOutParam()), RTEXITCODE_FAILURE); + } + + switch (cmd.mAction) + { + case USBFilterCmd::Add: + { + if (cmd.mGlobal) + { + ComPtr<IHostUSBDeviceFilter> flt; + CHECK_ERROR_BREAK(host, CreateUSBDeviceFilter(f.mName.raw(), + flt.asOutParam())); + + if (!f.mActive.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive)); + if (!f.mVendorId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw())); + if (!f.mProductId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw())); + if (!f.mRevision.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw())); + if (!f.mManufacturer.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw())); + if (!f.mProduct.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Product)(f.mProduct.raw())); + if (!f.mPort.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Port)(f.mPort.raw())); + if (!f.mSerialNumber.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw())); + if (!f.mMaskedInterfaces.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces)); + + if (f.mAction != USBDeviceFilterAction_Null) + CHECK_ERROR_BREAK(flt, COMSETTER(Action)(f.mAction)); + + CHECK_ERROR_BREAK(host, InsertUSBDeviceFilter(cmd.mIndex, flt)); + } + else + { + ComPtr<IUSBDeviceFilter> flt; + CHECK_ERROR_BREAK(flts, CreateDeviceFilter(f.mName.raw(), + flt.asOutParam())); + + if (!f.mActive.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive)); + if (!f.mVendorId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw())); + if (!f.mProductId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw())); + if (!f.mRevision.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw())); + if (!f.mManufacturer.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw())); + if (!f.mProduct.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Product)(f.mProduct.raw())); + if (!f.mPort.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Port)(f.mPort.raw())); + if (!f.mRemote.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Remote)(f.mRemote.raw())); + if (!f.mSerialNumber.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw())); + if (!f.mMaskedInterfaces.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces)); + + CHECK_ERROR_BREAK(flts, InsertDeviceFilter(cmd.mIndex, flt)); + } + break; + } + case USBFilterCmd::Modify: + { + if (cmd.mGlobal) + { + SafeIfaceArray <IHostUSBDeviceFilter> coll; + CHECK_ERROR_BREAK(host, COMGETTER(USBDeviceFilters)(ComSafeArrayAsOutParam(coll))); + + ComPtr<IHostUSBDeviceFilter> flt = coll[cmd.mIndex]; + + if (!f.mName.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Name)(f.mName.raw())); + if (!f.mActive.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive)); + if (!f.mVendorId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw())); + if (!f.mProductId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw())); + if (!f.mRevision.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw())); + if (!f.mManufacturer.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw())); + if (!f.mProduct.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Product)(f.mProduct.raw())); + if (!f.mPort.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Port)(f.mPort.raw())); + if (!f.mSerialNumber.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw())); + if (!f.mMaskedInterfaces.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces)); + + if (f.mAction != USBDeviceFilterAction_Null) + CHECK_ERROR_BREAK(flt, COMSETTER(Action)(f.mAction)); + } + else + { + SafeIfaceArray <IUSBDeviceFilter> coll; + CHECK_ERROR_BREAK(flts, COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(coll))); + + ComPtr<IUSBDeviceFilter> flt = coll[cmd.mIndex]; + + if (!f.mName.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Name)(f.mName.raw())); + if (!f.mActive.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive)); + if (!f.mVendorId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw())); + if (!f.mProductId.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw())); + if (!f.mRevision.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw())); + if (!f.mManufacturer.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw())); + if (!f.mProduct.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Product)(f.mProduct.raw())); + if (!f.mPort.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Port)(f.mPort.raw())); + if (!f.mRemote.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(Remote)(f.mRemote.raw())); + if (!f.mSerialNumber.isEmpty()) + CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw())); + if (!f.mMaskedInterfaces.isNull()) + CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces)); + } + break; + } + case USBFilterCmd::Remove: + { + if (cmd.mGlobal) + { + ComPtr<IHostUSBDeviceFilter> flt; + CHECK_ERROR_BREAK(host, RemoveUSBDeviceFilter(cmd.mIndex)); + } + else + { + ComPtr<IUSBDeviceFilter> flt; + CHECK_ERROR_BREAK(flts, RemoveDeviceFilter(cmd.mIndex, flt.asOutParam())); + } + break; + } + default: + break; + } + + if (cmd.mMachine) + { + if (SUCCEEDED(hrc)) + { + /* commit the session */ + CHECK_ERROR(cmd.mMachine, SaveSettings()); + } + /* close the session */ + a->session->UnlockMachine(); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +RTEXITCODE handleUSBDevSource(HandlerArg *a) +{ + HRESULT hrc = S_OK; + + /* at least: 0: command, 1: source id */ + if (a->argc < 2) + return errorSyntax(Usb::tr("Not enough parameters")); + + ComPtr<IHost> host; + if (!strcmp(a->argv[0], "add")) + { + setCurrentSubcommand(HELP_SCOPE_USBDEVSOURCE_ADD); + + Bstr strBackend; + Bstr strAddress; + if (a->argc != 6) + return errorSyntax(Usb::tr("Invalid number of parameters")); + + for (int i = 2; i < a->argc; i++) + { + if (!strcmp(a->argv[i], "--backend")) + { + i++; + strBackend = a->argv[i]; + } + else if (!strcmp(a->argv[i], "--address")) + { + i++; + strAddress = a->argv[i]; + } + else + return errorSyntax(Usb::tr("Parameter \"%s\" is invalid"), a->argv[i]); + } + + SafeArray<BSTR> usbSourcePropNames; + SafeArray<BSTR> usbSourcePropValues; + + CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(host, AddUSBDeviceSource(strBackend.raw(), Bstr(a->argv[1]).raw(), strAddress.raw(), + ComSafeArrayAsInParam(usbSourcePropNames), ComSafeArrayAsInParam(usbSourcePropValues)), + RTEXITCODE_FAILURE); + } + else if (!strcmp(a->argv[0], "remove")) + { + setCurrentSubcommand(HELP_SCOPE_USBDEVSOURCE_REMOVE); + CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE); + CHECK_ERROR_RET(host, RemoveUSBDeviceSource(Bstr(a->argv[1]).raw()), RTEXITCODE_FAILURE); + } + + return SUCCEEDED(hrc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; +} + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageUpdateCheck.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageUpdateCheck.cpp new file mode 100644 index 00000000..5b66b70b --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageUpdateCheck.cpp @@ -0,0 +1,392 @@ +/* $Id: VBoxManageUpdateCheck.cpp $ */ +/** @file + * VBoxManage - The 'updatecheck' command. + */ + +/* + * Copyright (C) 2020-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <VBox/com/com.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/VirtualBox.h> +#include <VBox/com/array.h> + +#include <iprt/buildconfig.h> +#include <VBox/version.h> + +#include <VBox/log.h> +#include <iprt/getopt.h> +#include <iprt/stream.h> +#include <iprt/ctype.h> +#include <iprt/message.h> + +#include "VBoxManage.h" + +DECLARE_TRANSLATION_CONTEXT(UpdateCheck); + +using namespace com; // SafeArray + + +static RTEXITCODE doUpdateList(int argc, char **argv, ComPtr<IUpdateAgent> pUpdateAgent) +{ + /* + * Parse options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--machine-readable", 'm', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0); + AssertRCReturn(vrc, RTEXITCODE_INIT); + + bool fMachineReadable = false; + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'm': + fMachineReadable = true; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* + * Do the work. + */ + BOOL fEnabled; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Enabled)(&fEnabled), RTEXITCODE_FAILURE); + if (fMachineReadable) + outputMachineReadableBool("enabled", &fEnabled); + else + RTPrintf(UpdateCheck::tr("Enabled: %s\n"), + fEnabled ? UpdateCheck::tr("yes") : UpdateCheck::tr("no")); + + ULONG cCheckCount; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(CheckCount)(&cCheckCount), RTEXITCODE_FAILURE); + if (fMachineReadable) + outputMachineReadableULong("count", &cCheckCount); + else + RTPrintf(UpdateCheck::tr("Count: %u\n"), cCheckCount); + + ULONG uCheckFreqSeconds; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(CheckFrequency)(&uCheckFreqSeconds), RTEXITCODE_FAILURE); + + ULONG uCheckFreqDays = uCheckFreqSeconds / RT_SEC_1DAY; + + if (fMachineReadable) + outputMachineReadableULong("frequency-days", &uCheckFreqDays); + else if (uCheckFreqDays == 0) + RTPrintf(UpdateCheck::tr("Frequency: Never\n")); + else if (uCheckFreqDays == 1) + RTPrintf(UpdateCheck::tr("Frequency: Every day\n")); + else + RTPrintf(UpdateCheck::tr("Frequency: Every %u days\n"), uCheckFreqDays); + + UpdateChannel_T enmUpdateChannel; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Channel)(&enmUpdateChannel), RTEXITCODE_FAILURE); + const char *psz; + const char *pszMachine; + switch (enmUpdateChannel) + { + case UpdateChannel_Stable: + psz = UpdateCheck::tr("Stable - new minor and maintenance releases"); + pszMachine = "stable"; + break; + case UpdateChannel_All: + psz = UpdateCheck::tr("All releases - new minor, maintenance, and major releases"); + pszMachine = "all-releases"; + break; + case UpdateChannel_WithBetas: + psz = UpdateCheck::tr("With Betas - new minor, maintenance, major, and beta releases"); + pszMachine = "with-betas"; + break; + default: + AssertFailed(); + psz = UpdateCheck::tr("Unset"); + pszMachine = "invalid"; + break; + } + if (fMachineReadable) + outputMachineReadableString("channel", pszMachine); + else + RTPrintf(UpdateCheck::tr("Channel: %s\n"), psz); + + Bstr bstrVal; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(LastCheckDate)(bstrVal.asOutParam()), + RTEXITCODE_FAILURE); + if (fMachineReadable) + outputMachineReadableString("last-check-date", &bstrVal); + else if (bstrVal.isNotEmpty()) + RTPrintf(UpdateCheck::tr("Last Check Date: %ls\n"), bstrVal.raw()); + + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(RepositoryURL)(bstrVal.asOutParam()), RTEXITCODE_FAILURE); + if (fMachineReadable) + outputMachineReadableString("repo-url", &bstrVal); + else + RTPrintf(UpdateCheck::tr("Repository: %ls\n"), bstrVal.raw()); + + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE doUpdateModify(int argc, char **argv, ComPtr<IUpdateAgent> pUpdateAgent) +{ + /* + * Parse options. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--enable", 'e', RTGETOPT_REQ_NOTHING }, + { "--disable", 'd', RTGETOPT_REQ_NOTHING }, + { "--channel", 'c', RTGETOPT_REQ_STRING }, + { "--frequency", 'f', RTGETOPT_REQ_UINT32 }, + }; + + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0); + AssertRCReturn(vrc, RTEXITCODE_INIT); + + int fEnabled = -1; /* Tristate: -1 (not modified), false, true. */ + UpdateChannel_T enmChannel = (UpdateChannel_T)-1; + uint32_t cFrequencyDays = 0; + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'e': + fEnabled = true; + break; + + case 'd': + fEnabled = false; + break; + + case 'c': + if (!RTStrICmp(ValueUnion.psz, "stable")) + enmChannel = UpdateChannel_Stable; + else if (!RTStrICmp(ValueUnion.psz, "withbetas")) + enmChannel = UpdateChannel_WithBetas; + /** @todo UpdateChannel_WithTesting once supported. */ + else if (!RTStrICmp(ValueUnion.psz, "all")) + enmChannel = UpdateChannel_All; + else + return errorArgument(UpdateCheck::tr("Invalid channel specified: '%s'"), ValueUnion.psz); + break; + + case 'f': + cFrequencyDays = ValueUnion.u32; + if (cFrequencyDays == 0) + return errorArgument(UpdateCheck::tr("The update frequency cannot be zero")); + break; + + /** @todo Add more options like repo handling etc. */ + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + if ( fEnabled == -1 + && enmChannel == (UpdateChannel_T)-1 + && cFrequencyDays == 0) + return errorSyntax(UpdateCheck::tr("No change requested")); + + /* + * Make the changes. + */ + if (enmChannel != (UpdateChannel_T)-1) + { + CHECK_ERROR2I_RET(pUpdateAgent, COMSETTER(Channel)(enmChannel), RTEXITCODE_FAILURE); + } + if (fEnabled != -1) + { + CHECK_ERROR2I_RET(pUpdateAgent, COMSETTER(Enabled)((BOOL)fEnabled), RTEXITCODE_FAILURE); + } + if (cFrequencyDays) + { + CHECK_ERROR2I_RET(pUpdateAgent, COMSETTER(CheckFrequency)(cFrequencyDays * RT_SEC_1DAY), RTEXITCODE_FAILURE); + } + return RTEXITCODE_SUCCESS; +} + +static RTEXITCODE doUpdateCheck(int argc, char **argv, ComPtr<IUpdateAgent> pUpdateAgent) +{ + /* + * Parse arguments. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--machine-readable", 'm', RTGETOPT_REQ_NOTHING } + }; + RTGETOPTSTATE GetState; + int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /* First */, 0); + AssertRCReturn(vrc, RTEXITCODE_INIT); + + bool fMachineReadable = false; + + int c; + RTGETOPTUNION ValueUnion; + while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0) + { + switch (c) + { + case 'm': + fMachineReadable = true; + break; + + default: + return errorGetOpt(c, &ValueUnion); + } + } + + /* + * Do the work. + */ + Bstr bstrName; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Name)(bstrName.asOutParam()), RTEXITCODE_FAILURE); + + if (!fMachineReadable) + RTPrintf(UpdateCheck::tr("Checking for a new %ls version...\n"), bstrName.raw()); + + /* + * We don't call CHECK_ERROR2I_RET(pHostUpdate, VBoxUpdate(updateCheckType, ...); here so we can check for a specific + * return value indicating update checks are disabled. + */ + ComPtr<IProgress> pProgress; + HRESULT hrc = pUpdateAgent->CheckFor(pProgress.asOutParam()); + if (FAILED(hrc)) + { + if (pProgress.isNull()) + RTStrmPrintf(g_pStdErr, UpdateCheck::tr("Failed to create update progress object: %Rhrc\n"), hrc); + else + com::GlueHandleComError(pUpdateAgent, "HostUpdate(UpdateChannel_Stable, pProgress.asOutParam())", + hrc, __FILE__, __LINE__); + return RTEXITCODE_FAILURE; + } + + /* HRESULT hrc = */ showProgress(pProgress, fMachineReadable ? SHOW_PROGRESS_NONE : SHOW_PROGRESS); + CHECK_PROGRESS_ERROR_RET(pProgress, (UpdateCheck::tr("Checking for update failed.")), RTEXITCODE_FAILURE); + + UpdateState_T updateState; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(State)(&updateState), RTEXITCODE_FAILURE); + + BOOL const fUpdateNeeded = updateState == UpdateState_Available; + if (fMachineReadable) + outputMachineReadableBool("update-needed", &fUpdateNeeded); + + switch (updateState) + { + case UpdateState_Available: + { + Bstr bstrUpdateVersion; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(Version)(bstrUpdateVersion.asOutParam()), RTEXITCODE_FAILURE); + Bstr bstrUpdateURL; + CHECK_ERROR2I_RET(pUpdateAgent, COMGETTER(DownloadUrl)(bstrUpdateURL.asOutParam()), RTEXITCODE_FAILURE); + + if (!fMachineReadable) + RTPrintf(UpdateCheck::tr( + "A new version of %ls has been released! Version %ls is available at virtualbox.org.\n" + "You can download this version here: %ls\n"), + bstrName.raw(), bstrUpdateVersion.raw(), bstrUpdateURL.raw()); + else + { + outputMachineReadableString("update-version", &bstrUpdateVersion); + outputMachineReadableString("update-url", &bstrUpdateURL); + } + + break; + } + + case UpdateState_NotAvailable: + { + if (!fMachineReadable) + RTPrintf(UpdateCheck::tr("You are already running the most recent version of %ls.\n"), bstrName.raw()); + break; + } + + case UpdateState_Canceled: + break; + + case UpdateState_Error: + RT_FALL_THROUGH(); + default: + { + if (!fMachineReadable) + RTPrintf(UpdateCheck::tr("Something went wrong while checking for updates!\n" + "Please check network connection and try again later.\n")); + break; + } + } + + return RTEXITCODE_SUCCESS; +} + +/** + * Handles the 'updatecheck' command. + * + * @returns Appropriate exit code. + * @param a Handler argument. + */ +RTEXITCODE handleUpdateCheck(HandlerArg *a) +{ + ComPtr<IHost> pHost; + CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(pHost.asOutParam()), RTEXITCODE_FAILURE); + + ComPtr<IUpdateAgent> pUpdate; + CHECK_ERROR2I_RET(pHost, COMGETTER(UpdateHost)(pUpdate.asOutParam()), RTEXITCODE_FAILURE); + /** @todo Add other update agents here. */ + + if (a->argc < 1) + return errorNoSubcommand(); + if (!RTStrICmp(a->argv[0], "perform")) + { + setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_PERFORM); + return doUpdateCheck(a->argc - 1, &a->argv[1], pUpdate); + } + if (!RTStrICmp(a->argv[0], "list")) + { + setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_LIST); + return doUpdateList(a->argc - 1, &a->argv[1], pUpdate); + } + if (!RTStrICmp(a->argv[0], "modify")) + { + setCurrentSubcommand(HELP_SCOPE_UPDATECHECK_MODIFY); + return doUpdateModify(a->argc - 1, &a->argv[1], pUpdate); + } + return errorUnknownSubcommand(a->argv[0]); +} + +/* vi: set tabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageUtils.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageUtils.cpp new file mode 100644 index 00000000..ad3fc508 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageUtils.cpp @@ -0,0 +1,131 @@ +/* $Id: VBoxManageUtils.cpp $ */ +/** @file + * VBoxManageUtils.h - VBoxManage utility functions. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "VBoxManageUtils.h" +#include "VBoxManage.h" + +#include <iprt/message.h> +#include <iprt/string.h> + +#include <VBox/com/array.h> +#include <VBox/com/errorprint.h> +#include <VBox/com/string.h> + +using namespace com; + +DECLARE_TRANSLATION_CONTEXT(Utils); + +unsigned int getMaxNics(const ComPtr<IVirtualBox> &pVirtualBox, + const ComPtr<IMachine> &pMachine) +{ + ULONG NetworkAdapterCount = 0; + do { + HRESULT hrc; + + ComPtr<ISystemProperties> info; + CHECK_ERROR_BREAK(pVirtualBox, COMGETTER(SystemProperties)(info.asOutParam())); + + ChipsetType_T aChipset; + CHECK_ERROR_BREAK(pMachine, COMGETTER(ChipsetType)(&aChipset)); + + CHECK_ERROR_BREAK(info, GetMaxNetworkAdapters(aChipset, &NetworkAdapterCount)); + } while (0); + + return (unsigned int)NetworkAdapterCount; +} + + +/** + * API does NOT verify that whether the interface name set as the + * bridged or host-only interface of a NIC is valid. Warn the user if + * IHost doesn't seem to know about it (non-fatal). + */ +void verifyHostNetworkInterfaceName(const ComPtr<IVirtualBox> &pVirtualBox, + const char *pszTargetName, + HostNetworkInterfaceType_T enmTargetType) +{ + HRESULT hrc; + + AssertReturnVoid( enmTargetType == HostNetworkInterfaceType_Bridged + || enmTargetType == HostNetworkInterfaceType_HostOnly); + + ComPtr<IHost> host; + hrc = pVirtualBox->COMGETTER(Host)(host.asOutParam()); + if (FAILED(hrc)) + return; + + SafeIfaceArray<IHostNetworkInterface> ifs; + hrc = host->COMGETTER(NetworkInterfaces)(ComSafeArrayAsOutParam(ifs)); + if (FAILED(hrc)) + return; + + for (size_t i = 0; i < ifs.size(); ++i) + { + const ComPtr<IHostNetworkInterface> iface = ifs[i]; + + Bstr bstrName; + hrc = iface->COMGETTER(Name)(bstrName.asOutParam()); + if (FAILED(hrc)) + return; + + if (!bstrName.equals(pszTargetName)) + continue; + + /* we found the interface but is it the right type? */ + HostNetworkInterfaceType_T enmType; + hrc = iface->COMGETTER(InterfaceType)(&enmType); + if (FAILED(hrc)) + return; + + if (enmType == enmTargetType) + return; /* seems ok */ + + const char *pszTypeName; + char a_szUnknownTypeBuf[32]; + switch (enmType) + { + case HostNetworkInterfaceType_Bridged: + pszTypeName = Utils::tr("type bridged"); + break; + + case HostNetworkInterfaceType_HostOnly: + pszTypeName = Utils::tr("type host-only"); + break; + + default: + RTStrPrintf(a_szUnknownTypeBuf, sizeof(a_szUnknownTypeBuf), + Utils::tr("unknown type %RU32"), enmType); + pszTypeName = a_szUnknownTypeBuf; + break; + } + + RTMsgWarning(Utils::tr("Interface \"%s\" is of %s"), pszTargetName, pszTypeName); + return; + } + + RTMsgWarning(Utils::tr("Interface \"%s\" doesn't seem to exist"), pszTargetName); +} diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageUtils.h b/src/VBox/Frontends/VBoxManage/VBoxManageUtils.h new file mode 100644 index 00000000..55241c37 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/VBoxManageUtils.h @@ -0,0 +1,45 @@ +/* $Id: VBoxManageUtils.h $ */ +/** @file + * VBoxManageUtils.h - Declarations for VBoxManage utility functions. + */ + +/* + * Copyright (C) 2006-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#ifndef VBOX_INCLUDED_SRC_VBoxManage_VBoxManageUtils_h +#define VBOX_INCLUDED_SRC_VBoxManage_VBoxManageUtils_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/com/com.h> +#include <VBox/com/ptr.h> +#include <VBox/com/VirtualBox.h> + +unsigned int getMaxNics(const ComPtr<IVirtualBox> &pVirtualBox, + const ComPtr<IMachine> &pMachine); + +void verifyHostNetworkInterfaceName(const ComPtr<IVirtualBox> &pVirtualBox, + const char *pszTargetName, + HostNetworkInterfaceType_T enmTargetType); + +#endif /* !VBOX_INCLUDED_SRC_VBoxManage_VBoxManageUtils_h */ diff --git a/src/VBox/Frontends/VBoxManage/nls/ApprovedLanguages.kmk b/src/VBox/Frontends/VBoxManage/nls/ApprovedLanguages.kmk new file mode 100644 index 00000000..de405a5d --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/nls/ApprovedLanguages.kmk @@ -0,0 +1,40 @@ +# $Id: ApprovedLanguages.kmk $ +## @file +# ApprovedLanguages.kmk - List of approved VBoxManage translations. +# + +# +# Copyright (C) 2007-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +# The list of approved VBoxManage languages. +VBOX_APPROVED_VBOXMANAGE_LANGUAGES := \ + ru + +# The list of approved VBoxManage language codes for built-in docbook +# help. Order matters for codes in the case of a language used in +# multiple countries. The language code used when no country is +# specified should be placed before other codes with the same language. +# For example: if en_US, en_UK and en_AU are approved the en_US should +# be placed before others allowing en_US to be used when the user +# specifies "en" as the desired language. +VBOX_APPROVED_VBOXMANAGE_DOCBOOK_LANGUAGES := \ + ru_RU diff --git a/src/VBox/Frontends/VBoxManage/nls/VBoxManageNls_ru.ts b/src/VBox/Frontends/VBoxManage/nls/VBoxManageNls_ru.ts new file mode 100644 index 00000000..6cf00e15 --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/nls/VBoxManageNls_ru.ts @@ -0,0 +1,12354 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru"> +<context> + <name>Appliance</name> + <message> + <location filename="../VBoxManageAppliance.cpp" line="256"/> + <location filename="../VBoxManageAppliance.cpp" line="1551"/> + <source>Option "%s" can't be used together with "--cloud" option.</source> + <translation>ŠŠæŃŠøŃ "%s" Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½Š° Š²Š¼ŠµŃŃŠµ Ń "--cloud".</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="259"/> + <location filename="../VBoxManageAppliance.cpp" line="334"/> + <location filename="../VBoxManageAppliance.cpp" line="1554"/> + <location filename="../VBoxManageAppliance.cpp" line="1637"/> + <source>Value of option "%s" is out of range.</source> + <translation>ŠŠ½Š°ŃŠµŠ½ŠøŠµ Š¾ŠæŃŠøŠø "%s" Š²ŃŃ
Š¾Š“ŠøŃ Š·Š° Š³ŃŠ°Š½ŠøŃŃ Š“ŠøŠ°ŠæŠ°Š·Š¾Š½Š°.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="268"/> + <location filename="../VBoxManageAppliance.cpp" line="275"/> + <location filename="../VBoxManageAppliance.cpp" line="289"/> + <location filename="../VBoxManageAppliance.cpp" line="303"/> + <location filename="../VBoxManageAppliance.cpp" line="317"/> + <location filename="../VBoxManageAppliance.cpp" line="324"/> + <location filename="../VBoxManageAppliance.cpp" line="1562"/> + <source>Option "%s" requires preceding --vsys or --cloud option.</source> + <translation>ŠŠæŃŠøŃ "%s" ŃŃŠµŠ±ŃŠµŃ Š½Š°Š»ŠøŃŠøŃ ŠæŃŠµŠ“ŃŠµŃŃŠ²ŃŠµŃŠµŠ³Š¾ --vsys ŠøŠ»Šø --cloud.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="282"/> + <location filename="../VBoxManageAppliance.cpp" line="296"/> + <location filename="../VBoxManageAppliance.cpp" line="310"/> + <location filename="../VBoxManageAppliance.cpp" line="331"/> + <location filename="../VBoxManageAppliance.cpp" line="342"/> + <location filename="../VBoxManageAppliance.cpp" line="352"/> + <location filename="../VBoxManageAppliance.cpp" line="362"/> + <location filename="../VBoxManageAppliance.cpp" line="372"/> + <location filename="../VBoxManageAppliance.cpp" line="382"/> + <location filename="../VBoxManageAppliance.cpp" line="1569"/> + <location filename="../VBoxManageAppliance.cpp" line="1576"/> + <location filename="../VBoxManageAppliance.cpp" line="1583"/> + <location filename="../VBoxManageAppliance.cpp" line="1590"/> + <location filename="../VBoxManageAppliance.cpp" line="1597"/> + <location filename="../VBoxManageAppliance.cpp" line="1604"/> + <location filename="../VBoxManageAppliance.cpp" line="1611"/> + <location filename="../VBoxManageAppliance.cpp" line="1618"/> + <source>Option "%s" requires preceding --vsys option.</source> + <translation>ŠŠæŃŠøŃ "%s" ŃŃŠµŠ±ŃŠµŃ Š½Š°Š»ŠøŃŠøŃ ŠæŃŠµŠ“ŃŠµŃŃŠ²ŃŠµŃŠµŠ³Š¾ --vsys.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="345"/> + <location filename="../VBoxManageAppliance.cpp" line="355"/> + <location filename="../VBoxManageAppliance.cpp" line="365"/> + <location filename="../VBoxManageAppliance.cpp" line="375"/> + <location filename="../VBoxManageAppliance.cpp" line="385"/> + <source>Option "%s" requires preceding --unit option.</source> + <translation>ŠŠæŃŠøŃ "%s" ŃŃŠµŠ±ŃŠµŃ Š½Š°Š»ŠøŃŠøŃ ŠæŃŠµŠ“ŃŠµŃŃŠ²ŃŠµŃŠµŠ³Š¾ --unit.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="392"/> + <source>Invalid import options '%s' +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ Š¾ŠæŃŠøŠø ŠøŠ¼ŠæŠ¾ŃŃŠ° '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="401"/> + <location filename="../VBoxManageAppliance.cpp" line="1634"/> + <source>Option "%s" can't be used together with "--vsys" option.</source> + <translation>ŠŠæŃŠøŃ "%s" Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½Š° Š²Š¼ŠµŃŃŠµ Ń "--vsys".</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="410"/> + <location filename="../VBoxManageAppliance.cpp" line="417"/> + <location filename="../VBoxManageAppliance.cpp" line="424"/> + <location filename="../VBoxManageAppliance.cpp" line="1646"/> + <location filename="../VBoxManageAppliance.cpp" line="1653"/> + <location filename="../VBoxManageAppliance.cpp" line="1660"/> + <location filename="../VBoxManageAppliance.cpp" line="1667"/> + <location filename="../VBoxManageAppliance.cpp" line="1674"/> + <location filename="../VBoxManageAppliance.cpp" line="1681"/> + <location filename="../VBoxManageAppliance.cpp" line="1688"/> + <location filename="../VBoxManageAppliance.cpp" line="1695"/> + <location filename="../VBoxManageAppliance.cpp" line="1702"/> + <location filename="../VBoxManageAppliance.cpp" line="1709"/> + <location filename="../VBoxManageAppliance.cpp" line="1716"/> + <location filename="../VBoxManageAppliance.cpp" line="1723"/> + <location filename="../VBoxManageAppliance.cpp" line="1730"/> + <source>Option "%s" requires preceding --cloud option.</source> + <translation>ŠŠæŃŠøŃ "%s" ŃŃŠµŠ±ŃŠµŃ Š½Š°Š»ŠøŃŠøŃ ŠæŃŠµŠ“ŃŠµŃŃŠ²ŃŠµŃŠµŠ³Š¾ --cloud.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="433"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="440"/> + <source>Invalid option -%c</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń Š¾ŠæŃŠøŃ -%c</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="442"/> + <source>Invalid option case %i</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²Š°ŃŠøŠ°Š½Ń Š¾ŠæŃŠøŠø %i</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="445"/> + <source>unknown option: %s +</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="449"/> + <source>error: %Rrs</source> + <translation>ŠŃŠøŠ±ŠŗŠ°: %Rrs</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="455"/> + <source>Not enough arguments for "import" command.</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ¾Š² Š“Š»Ń ŠŗŠ¾Š¼Š°Š½Š“Ń "import".</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="477"/> + <source>Not enough arguments for import from the Cloud.</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ¾Š² Š“Š»Ń ŠøŠ¼ŠæŠ¾ŃŃŠ° ŠøŠ· Š¾Š±Š»Š°ŠŗŠ°.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="500"/> + <source>Appliance read failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="512"/> + <source>Interpreting %ls... +</source> + <translation>ŠŠ½ŃŠµŃŠæŃŠµŃŠ°ŃŠøŃ %ls... +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="544"/> + <source>Disks: +</source> + <translation>ŠŠøŃŠŗŠø: +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="565"/> + <source>Invalid index %RI32 with -vsys option; the OVF contains only %zu virtual system(s).</source> + <translation> + <numerusform>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI32 Ń Š¾ŠæŃŠøŠøŠø -vsys; OVF ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŃŠ¾Š»ŃŠŗŠ¾ %zu Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŃ ŃŠøŃŃŠµŠ¼Ń.</numerusform> + <numerusform>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI32 Ń Š¾ŠæŃŠøŠø -vsys; OVF ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŃŠ¾Š»ŃŠŗŠ¾ %zu Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠµ ŃŠøŃŃŠµŠ¼Ń.</numerusform> + <numerusform>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI32 Ń Š¾ŠæŃŠøŠøŠø -vsys; OVF ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŃŠ¾Š»ŃŠŗŠ¾ %zu Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŃ
ŃŠøŃŃŠµŠ¼.</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="600"/> + <source>Virtual system %u: +</source> + <translation>ŠŠøŃŃŃŠ°Š»ŃŠ½Š°Ń ŃŠøŃŃŠµŠ¼Š° %u: +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="630"/> + <source>%2u: OS type specified with --ostype: "%ls" +</source> + <translation>%2u: Š¢ŠøŠæ ŠŠ” ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠµŃŠµŠ· --ostype: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="634"/> + <source>%2u: Suggested OS type: "%ls" + (change with "--vsys %u --ostype <type>"; use "list ostypes" to list all possible values) +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½ŃŠ¹ ŃŠøŠæ ŠŠ”: "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --ostype <ŃŠøŠæ>"; ŠøŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ "list ostypes" Š“Š»Ń ŠæŃŠ¾ŃŠ¼Š¾ŃŃŠ° Š²ŃŠµŃ
Š²Š¾Š·Š¼Š¾Š¶Š½ŃŃ
Š·Š½Š°ŃŠµŠ½ŠøŠ¹) +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="643"/> + <source>%2u: VM name specified with --vmname: "%ls" +</source> + <translation>%2u: ŠŠ¼Ń ŠŠ, ŃŠŗŠ°Š·Š°Š½Š½Š¾Šµ ŃŠµŃŠµŠ· --vmname: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="647"/> + <source>%2u: Suggested VM name "%ls" + (change with "--vsys %u --vmname <name>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½Šµ ŠøŠ¼Ń ŠŠ "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --vmname <ŠøŠ¼Ń>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="653"/> + <source>%2u: Product (ignored): %ls +</source> + <translation>%2u: ŠŃŠ¾Š“ŃŠŗŃ (ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½): %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="658"/> + <source>%2u: ProductUrl (ignored): %ls +</source> + <translation>%2u: Url ŠæŃŠ¾Š“ŃŠŗŃŠ° (ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½): %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="663"/> + <source>%2u: Vendor (ignored): %ls +</source> + <translation>%2u: ŠŠ¾ŃŃŠ°Š²ŃŠøŠŗ (ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½): %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="668"/> + <source>%2u: VendorUrl (ignored): %ls +</source> + <translation>%2u: Url ŠæŠ¾ŃŃŠ°Š²ŃŠøŠŗŠ° (ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½): %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="673"/> + <source>%2u: Version (ignored): %ls +</source> + <translation>%2u: ŠŠµŃŃŠøŃ (ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½Š°): %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="681"/> + <source>%2u: Description specified with --description: "%ls" +</source> + <translation>%2u: ŠŠæŠøŃŠ°Š½ŠøŠµ, ŃŠŗŠ°Š·Š°Š½Š½Š¾Šµ ŃŠµŃŠµŠ· --description: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="685"/> + <source>%2u: Description "%ls" + (change with "--vsys %u --description <desc>") +</source> + <translation>%2u: ŠŠæŠøŃŠ°Š½ŠøŠµ "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --description <Š¾ŠæŠøŃŠ°Š½ŠøŠµ>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="696"/> + <source>%2u: End-user license agreement + (accept with "--vsys %u --eula accept"): + +%ls + +</source> + <translation>%2u: ŠŠøŃŠµŠ½Š·ŠøŠ¾Š½Š½Š¾Šµ ŃŠ¾Š³Š»Š°ŃŠµŠ½ŠøŠµ + (ŠæŃŠøŠ½ŃŃŃ ŃŠµŃŠµŠ· "--vsys %u --eula accept"): + +%ls + +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="703"/> + <source>%2u: End-user license agreement (accepted) +</source> + <translation>%2u: ŠŠøŃŠµŠ½Š·ŠøŠ¾Š½Š½Š¾Šµ ŃŠ¾Š³Š»Š°ŃŠµŠ½ŠøŠµ (ŠæŃŠøŠ½ŃŃŠ¾) +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="708"/> + <source>Argument to --eula must be either "show" or "accept".</source> + <translation>ŠŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --eula Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŠøŠ»Šø "show" ŠøŠ»Šø "accept".</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="711"/> + <source>%2u: End-user license agreement + (display with "--vsys %u --eula show"; + accept with "--vsys %u --eula accept") +</source> + <translation>%2u: ŠŠøŃŠµŠ½Š·ŠøŠ¾Š½Š½Š¾Šµ ŃŠ¾Š³Š»Š°ŃŠµŠ½ŠøŠµ + (ŠæŠ¾ŠŗŠ°Š·Š°ŃŃ ŃŠµŃŠµŠ· "--vsys %u --eula show"; + ŠæŃŠøŠ½ŃŃŃ ŃŠµŃŠµŠ· "--vsys %u --eula accept") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="727"/> + <source>%2u: No. of CPUs specified with --cpus: %ls +</source> + <translation>%2u: Š§ŠøŃŠ»Š¾ Š¦ŠŠ£ ŃŠŗŠ°Š·Š°Š½Š½ŃŃ
ŃŠµŃŠµŠ· --cpus: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="731"/> + <source>Argument to --cpus option must be a number greater than %d and less than %d.</source> + <translation>ŠŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --cpus Š“Š¾Š¶ŠµŠ½ Š±ŃŃŃ ŃŠøŃŠ»Š¾Š¼ Š±Š¾Š»ŃŃŠµ %d Šø Š¼ŠµŠ½ŃŃŠµ %d.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="735"/> + <source>%2u: Number of CPUs: %ls + (change with "--vsys %u --cpus <n>") +</source> + <translation>%2u: Š§ŠøŃŠ»Š¾ Š¦ŠŠ£: %ls + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --cpus <n>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="747"/> + <source>%2u: Guest memory specified with --memory: %ls MB +</source> + <translation>%2u: Š Š°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń, ŃŠŗŠ°Š·Š°Š½Š½Š¾Š¹ ŃŠµŃŠµŠ· --memory: %ls MB +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="751"/> + <source>Argument to --memory option must be a non-negative number.</source> + <translation>ŠŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --memory Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ Š½ŠµŠ¾ŃŃŠøŃŠ°ŃŠµŠ»ŃŠ½ŃŠ¼ ŃŠøŃŠ»Š¾Š¼.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="754"/> + <source>%2u: Guest memory: %ls MB + (change with "--vsys %u --memory <MB>") +</source> + <translation>%2u: Š Š°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń: %ls MB + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --memory <MB>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="762"/> + <source>%2u: IDE controller, type %ls -- disabled +</source> + <translation>%2u: IDE ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="768"/> + <source>%2u: IDE controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: IDE ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="778"/> + <source>%2u: SATA controller, type %ls -- disabled +</source> + <translation>%2u: SATA ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="784"/> + <source>%2u: SATA controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: SATA ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="794"/> + <source>%2u: SAS controller, type %ls -- disabled +</source> + <translation>%2u: SAS ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="800"/> + <source>%2u: SAS controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: SAS ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="810"/> + <source>%2u: SCSI controller, type %ls -- disabled +</source> + <translation>%2u: SCSI ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="821"/> + <source>%2u: SCSI controller, type set with --unit %u --scsitype: "%ls" +</source> + <translation>%2u: SCSI ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½ ŃŠµŃŠµŠ· --unit %u --scsitype: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="827"/> + <source>%2u: SCSI controller, type %ls + (change with "--vsys %u --unit %u --scsitype {BusLogic|LsiLogic}"; + disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: SCSI ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --scsitype {BusLogic|LsiLogic}"; + Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="839"/> + <source>%2u: VirtioSCSI controller, type %ls -- disabled +</source> + <translation>%2u: VirtioSCSI ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="845"/> + <source>%2u: VirtioSCSI controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: VirtioSCSI ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ, ŃŠøŠæ %ls + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="855"/> + <source>%2u: Hard disk image: source image=%ls -- disabled +</source> + <translation>%2u: ŠŠ±ŃŠ°Š· Š¶ŠµŃŃŠŗŠ¾Š³Š¾ Š“ŠøŃŠŗŠ°: Š¾Š±ŃŠ°Š· ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°=%ls -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <source>Option --ImportToVDI shall not be used together with manually set target path.</source> + <translation type="vanished">ŠŠæŃŠøŃ --ImportToVDI Š½Šµ Š“Š¾Š»Š¶Š½Š° ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŃŃŃ Š²Š¼ŠµŃŃŠµ Ń ŠæŃŃŠµŠ¼ Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ, ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¼ Š²ŃŃŃŠ½ŃŃ.</translation> + </message> + <message> + <source>%2u: Hard disk image: source image=%ls, target path=%ls, %ls +</source> + <translation type="vanished">%2u: ŠŠ±ŃŠ°Š· Š¶ŠµŃŃŠŗŠ¾Š³Š¾ Š“ŠøŃŠŗŠ°: Š¾Š±ŃŠ°Š· ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°=%ls, ŠæŃŃŃ Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ=%ls, %ls +</translation> + </message> + <message> + <source>%2u: Hard disk image: source image=%ls, target path=%ls, %ls + (change target path with "--vsys %u --unit %u --disk path"; + disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="vanished">%2u: ŠŠ±ŃŠ°Š· Š¶ŠµŃŃŠŗŠ¾Š³Š¾ Š“ŠøŃŠŗŠ°: Š¾Š±ŃŠ°Š· ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°=%ls, ŠæŃŃŃ Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ=%ls, %ls + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŠæŃŃŃ Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --disk ŠæŃŃŃ"; + Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="870"/> + <source>Option --ImportToVDI can not be used together with a manually set target path.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="898"/> + <source>Invalid controller value: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="903"/> + <location filename="../VBoxManageAppliance.cpp" line="970"/> + <source>Invalid storage controller specified: %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="916"/> + <source>Invalid port value: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="931"/> + <source>Failed to extract controller value from ExtraConfig: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="937"/> + <source>Failed to extract channel value from ExtraConfig: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="963"/> + <source>Device already attached to controller %u at this port (%u) location.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1001"/> + <source>Illegal port value: %u. For %ls controllers the only valid values are 0 to %lu (inclusive)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1023"/> + <source>%2u: Hard disk image specified with --disk: source image=%ls, target path=%ls, %s + (change controller with "--vsys %u --unit %u --controller <index>"; + change controller port with "--vsys %u --unit %u --port <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1035"/> + <source>%2u: Hard disk image specified with --disk and --controller: source image=%ls, target path=%ls, %s + (change controller port with "--vsys %u --unit %u --port <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1045"/> + <source>%2u: Hard disk image specified with --disk and --port: source image=%ls, target path=%ls, %s + (change controller with "--vsys %u --unit %u --controller <index>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1055"/> + <source>%2u: Hard disk image specified with --controller and --port: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1065"/> + <source>%2u: Hard disk image specified with --port: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path"; + change controller with "--vsys %u --unit %u --controller <index>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1077"/> + <source>%2u: Hard disk image specified with --controller: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path"; + change controller port with "--vsys %u --unit %u --port <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1089"/> + <source>%2u: Hard disk image specified with --disk and --controller and --port: source image=%ls, target path=%ls, %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1174"/> + <source>%2u: Hard disk image: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path"; + change controller with "--vsys %u --unit %u --controller <index>"; + change controller port with "--vsys %u --unit %u --port <n>"; + disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1191"/> + <source>%2u: CD-ROM -- disabled +</source> + <translation>%2u: CD-ROM -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1196"/> + <source>%2u: CD-ROM + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: CD-ROM + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1204"/> + <source>%2u: Floppy -- disabled +</source> + <translation>%2u: Š¤Š»Š¾ŠæŠæŠø -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1209"/> + <source>%2u: Floppy + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: Š¤Š»Š¾ŠæŠæŠø + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1215"/> + <source>%2u: Network adapter: orig %ls, config %ls, extra %ls +</source> + <translation>%2u: Š”ŠµŃŠµŠ²Š¾Š¹ Š°Š“Š°ŠæŃŠµŃ: Š¾ŃŠøŠ³. %ls, ŠŗŠ¾Š½ŃŠøŠ³. %ls, ŃŠŗŃŃŃŠ° %ls +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1225"/> + <source>%2u: USB controller -- disabled +</source> + <translation>%2u: USB ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ -- Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1230"/> + <source>%2u: USB controller + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: USB ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1238"/> + <source>%2u: Sound card "%ls" -- disabled +</source> + <translation>%2u: ŠŃŠ“ŠøŠ¾ ŠŗŠ°ŃŃŠ° "%ls" -- Š¾ŃŠŗŠ»ŃŃŠµŠ½Š° +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1244"/> + <source>%2u: Sound card (appliance expects "%ls", can change on import) + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation>%2u: ŠŃŠ“ŠøŠ¾ ŠŗŠ°ŃŃŠ° (ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ Š¾Š¶ŠøŠ“Š°ŠµŃ "%ls", Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½Š° ŠæŃŠø ŠøŠ¼ŠæŠ¾ŃŃŠµ) + (Š¾ŃŠŗŠ»ŃŃŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --unit %u --ignore") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1256"/> + <source>%2u: VM settings file name specified with --settingsfile: "%ls" +</source> + <translation>%2u: ŠŠ¼Ń ŃŠ°Š¹Š»Š° Š½Š°ŃŃŃŠ¾ŠµŠŗ ŠŠ ŃŠŗŠ°Š·Š°Š½Š½Š¾Šµ ŃŠµŃŠµŠ· --settingsfile: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1260"/> + <source>%2u: Suggested VM settings file name "%ls" + (change with "--vsys %u --settingsfile <filename>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½Š¾Šµ ŠøŠ¼Ń ŃŠ°Š¹Š»Š° Š½Š°ŃŃŃŠ¾ŠµŠŗ ŠŠ "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --settingsfile <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1269"/> + <source>%2u: VM base folder specified with --basefolder: "%ls" +</source> + <translation>%2u: ŠŃŠ½Š¾Š²Š½Š°Ń ŠæŠ°ŠæŠŗŠ° ŠŠ ŃŠŗŠ°Š·Š°Š½Š½Š°Ń ŃŠµŃŠµŠ· --basefolder: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1273"/> + <source>%2u: Suggested VM base folder "%ls" + (change with "--vsys %u --basefolder <path>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½Š°Ń Š¾ŃŠ½Š¾Š²Š½Š°Ń ŠæŠ°ŠæŠŗŠ° ŠŠ "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --basefolder <ŠæŃŃŃ>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1282"/> + <source>%2u: VM group specified with --group: "%ls" +</source> + <translation>%2u: ŠŃŃŠæŠæŠ° ŠŠ, ŃŠŗŠ°Š·Š°Š½Š½Š°Ń ŃŠµŃŠµŠ· --group: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1286"/> + <source>%2u: Suggested VM group "%ls" + (change with "--vsys %u --group <group>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½Š°Ń Š³ŃŃŠæŠæŠ° ŠŠ "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--vsys %u --group <Š³ŃŃŠæŠæŠ°>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1292"/> + <source>%2u: Suggested cloud shape "%ls" +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½Š°Ń Š¾Š±Š»Š°ŃŠ½Š°Ń ŃŠ¾ŃŠ¼Š° "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1300"/> + <source>%2u: Cloud bucket id specified with --cloudbucket: "%ls" +</source> + <translation>%2u: ID Š¾Š±Š»Š°ŃŠ½Š¾Š¹ ŠŗŠ¾ŃŠ·ŠøŠ½Ń, ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠµŃŠµŠ· --cloudbucket: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1304"/> + <source>%2u: Suggested cloud bucket id "%ls" + (change with "--cloud %u --cloudbucket <id>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½ŃŠ¹ ID Š¾Š±Š»Š°ŃŠ½Š¾Š¹ ŠŗŠ¾ŃŠ·ŠøŠ½Ń "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--cloud %u --cloudbucket <id>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1313"/> + <source>%2u: Cloud profile name specified with --cloudprofile: "%ls" +</source> + <translation>%2u: ŠŠ¼Ń Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŠæŃŠ¾ŃŠøŠ»Ń, ŃŠŗŠ°Š·Š°Š½Š½Š¾Š³Š¾ ŃŠµŃŠµŠ· --cloudprofile: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1317"/> + <source>%2u: Suggested cloud profile name "%ls" + (change with "--cloud %u --cloudprofile <id>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½Š¾Šµ ŠøŠ¼Ń Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŠæŃŠ¾ŃŠøŠ»Ń "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--cloud %u --cloudprofile <id>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1326"/> + <source>%2u: Cloud instance id specified with --cloudinstanceid: "%ls" +</source> + <translation>%2u: ID Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ°, ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠµŃŠµŠ· --cloudinstanceid: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1330"/> + <source>%2u: Suggested cloud instance id "%ls" + (change with "--cloud %u --cloudinstanceid <id>") +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½ŃŠ¹ ID Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° "%ls" + (ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠµŃŠµŠ· "--cloud %u --cloudinstanceid <id>") +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1336"/> + <source>%2u: Suggested cloud base image id "%ls" +</source> + <translation>%2u: ŠŃŠµŠ“Š»Š¾Š¶ŠµŠ½Š½ŃŠ¹ ID Suggested cloud base image id "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1384"/> + <source>Cannot import until the license agreement listed above is accepted.</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŠøŠ·Š²ŠµŃŃŠø ŠøŠ¼ŠæŠ¾ŃŃ ŠæŠ¾ŠŗŠ° Š½Šµ ŠæŃŠøŠ½ŃŃŃ ŃŃŠ»Š¾Š²ŠøŃ Š»ŠøŃŠµŠ½Š·ŠøŠ¾Š½Š½Š¾Š³Š¾ ŃŠ¾Š³Š»Š°ŃŠµŠ½ŠøŃ, ŠæŠ¾ŠŗŠ°Š·Š°Š½Š½ŃŠµ Š²ŃŃŠµ.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1386"/> + <source>Cannot import until the %c license agreements listed above are accepted.</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŠøŠ·Š²ŠµŃŃŠø ŠøŠ¼ŠæŠ¾ŃŃ ŠæŠ¾ŠŗŠ° Š½Šµ ŠæŃŠøŠ½ŃŃŃ ŃŃŠ»Š¾Š²ŠøŃ Š»ŠøŃŠµŠ½Š·ŠøŠ¾Š½Š½Š¾Š³Š¾ ŃŠ¾Š³Š»Š°ŃŠµŠ½ŠøŃ %c, ŠæŠ¾ŠŗŠ°Š·Š°Š½Š½ŃŠµ Š²ŃŃŠµ.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1397"/> + <source>Appliance import failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŠøŠ·Š²ŠµŃŃŠø ŠøŠ¼ŠæŠ¾ŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1400"/> + <source>Successfully imported the appliance. +</source> + <translation>ŠŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ ŠøŠ¼ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½Š° ŃŃŠæŠµŃŠ½Š¾. +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1517"/> + <source>You can only specify --output once.</source> + <translation>--output Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1625"/> + <source>Invalid export options '%s' +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ Š¾ŠæŃŠøŠø ŠøŠ¼ŠæŠ¾ŃŃŠ° '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1751"/> + <source>unhandled option: -%c</source> + <translation>Š½ŠµŠ¾Š±ŃŠ°Š±Š¾ŃŠ°Š½Š½Š°Ń Š¾ŠæŃŠøŃ: -%c</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1753"/> + <source>unhandled option: %i</source> + <translation>Š½ŠµŠ¾Š±ŃŠ°Š±Š¾ŃŠ°Š½Š½Š°Ń Š¾ŠæŃŠøŃ: %i</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1756"/> + <source>unknown option: %s</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1771"/> + <source>At least one machine must be specified with the export command.</source> + <translation>ŠŠ°Šŗ Š¼ŠøŠ½ŠøŠ¼ŃŠ¼ Š¾Š“Š½Š° Š¼Š°ŃŠøŠ½Š° Š“Š¾Š»Š¶Š½Š° Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½Š° Š² ŠŗŠ¾Š¼Š°Š½Š“Šµ ŃŠŗŃŠæŠ¾ŃŃŠ°.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1775"/> + <source>Missing --output argument with export command.</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń --output Ń ŠŗŠ¾Š¼Š°Š½Š“Ń ŃŠŗŃŠæŠ¾ŃŃŠ°.</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="1789"/> + <source>Invalid index %RI32 with -vsys option; you specified only %zu virtual system(s).</source> + <translation> + <numerusform>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI32 Ń Š¾ŠæŃŠøŠø -vsys option; Š²Ń ŃŠŗŠ°Š·Š°Š»Šø ŃŠ¾Š»ŃŠŗŠ¾ %zu Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŃ ŃŠøŃŃŠµŠ¼Ń.</numerusform> + <numerusform>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI32 Ń Š¾ŠæŃŠøŠø -vsys option; Š²Ń ŃŠŗŠ°Š·Š°Š»Šø ŃŠ¾Š»ŃŠŗŠ¾ %zu Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠµ ŃŠøŃŃŠµŠ¼Ń.</numerusform> + <numerusform>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI32 Ń Š¾ŠæŃŠøŠø -vsys option; Š²Ń ŃŠŗŠ°Š·Š°Š»Šø ŃŠ¾Š»ŃŠŗŠ¾ %zu Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŃ
ŃŠøŃŃŠµŠ¼.</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1878"/> + <source>Cannot read license file "%s" which should be included in the virtual system %u.</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŃŠµŃŃŃ ŃŠ°Š¹Š» Š»ŠøŃŠµŠ½Š·ŠøŠø "%s", ŠŗŠ¾ŃŠ¾ŃŃŠ¹ Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ Š²ŠŗŠ»ŃŃŠµŠ½ Š² Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŃ ŃŠøŃŃŠµŠ¼Ń %u.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1941"/> + <source>Enter the passwords for the following identifiers to export the apppliance: +</source> + <translation>ŠŠ²ŠµŠ“ŠøŃŠµ ŠæŠ°ŃŠ¾Š»Ń Š“Š»Ń ŃŠ»ŠµŠ“ŃŃŃŠøŃ
ŠøŠ“ŠµŠ½ŃŠøŃŠøŠŗŠ°ŃŠ¾ŃŠ¾Š², ŃŃŠ¾Š±Ń ŃŠŗŃŠæŠ¾ŃŃŠøŃŠ¾Š²Š°ŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ: +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1948"/> + <source>Password ID %s:</source> + <translation>ID ŠæŠ°ŃŠ¾Š»Ń %s:</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1978"/> + <source>Appliance write failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŠøŃŠ°ŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="1981"/> + <source>Successfully exported %d machine(s). +</source> + <translation> + <numerusform>%d Š¼Š°ŃŠøŠ½Š° ŃŠŗŃŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½Š° ŃŃŠæŠµŃŠ½Š¾. +</numerusform> + <numerusform>%d Š¼Š°ŃŠøŠ½Ń ŃŠŗŃŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½Ń ŃŃŠæŠµŃŠ½Š¾. +</numerusform> + <numerusform>%d Š¼Š°ŃŠøŠ½ ŃŠŗŃŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½Š¾ ŃŃŠæŠµŃŠ½Š¾. +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2037"/> + <source>Creating a cloud instance... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ°... +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2042"/> + <source>Creating the cloud instance failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2054"/> + <source>A cloud instance with id '%s' (provider '%s') was created +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ Ń ID '%s' (ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ '%s') ŃŠ¾Š·Š“Š°Š½ +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2107"/> + <source>Failed to open OVA '%s' for updating: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŃŃŃŃ OVA '%s' Š“Š»Ń Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŃ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2113"/> + <source>Failed to open OVA '%s' as a TAR file: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŃŃŃŃ OVA '%s' ŠŗŠ°Šŗ ŃŠ°Š¹Š» TAR: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2120"/> + <source>Scanning OVA '%s' for a manifest and signature...</source> + <translation>Š”ŠŗŠ°Š½ŠøŃŠ¾Š²Š°Š½ŠøŠµ OVA '%s' Š½Š° Š½Š°Š»ŠøŃŠøŠµ Š¼Š°Š½ŠøŃŠµŃŃŠ° Šø ŠæŠ¾Š“ŠæŠøŃŠø...</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2136"/> + <source>RTVfsFsStrmNext returned %Rrc</source> + <translation>RTVfsFsStrmNext Š²Š¾Š·Š²ŃŠ°ŃŠøŠ» %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2152"/> + <source>OVA contains multiple manifests! first: %s second: %s</source> + <translation>OVA ŃŠ¾Š“ŠµŃŠ¶ŠøŃ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ Š¼Š°Š½ŠøŃŠµŃŃŠ¾Š²! ŠæŠµŃŠ²ŃŠ¹: %s Š²ŃŠ¾ŃŠ¾Š¹: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2156"/> + <location filename="../VBoxManageAppliance.cpp" line="2194"/> + <source>Unsupported OVA file ordering! Signature file ('%s') as succeeded by '%s'.</source> + <translation>ŠŠµŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠ¹ ŠæŠ¾ŃŃŠ“Š¾Šŗ ŃŠ°Š¹Š»Š¾Š² OVA! Š¤Š°Š¹Š» ŠæŠ¾Š“ŠæŠøŃŠø ('%s') ŠæŠ¾ŃŠ»Šµ '%s'.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2161"/> + <source>Found manifest file: %s</source> + <translation>ŠŠ°Š¹Š“ŠµŠ½ ŃŠ°Š¹Š» Š¼Š°Š½ŠøŃŠµŃŃŠ°: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2170"/> + <source>Failed to memorize the manifest: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŠ¾Š¼Š½ŠøŃŃ Š¼Š°Š½ŠøŃŠµŃŃ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2173"/> + <location filename="../VBoxManageAppliance.cpp" line="2414"/> + <location filename="../VBoxManageAppliance.cpp" line="2488"/> + <location filename="../VBoxManageAppliance.cpp" line="2647"/> + <source>Out of memory!</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø!</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2181"/> + <source>Multiple signature files! (%s)</source> + <translation>ŠŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŃŠ°Š¹Š»Š¾Š² ŠæŠ¾Š“ŠæŠøŃŠµŠ¹! (%s)</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2185"/> + <source>Found existing signature file: %s</source> + <translation>ŠŠ°Š¹Š“ŠµŠ½ ŃŃŃŠµŃŃŠ²ŃŃŃŠøŠ¹ ŃŠ°Š¹Š» ŃŠøŠ³Š½Š°ŃŃŃŃ: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2210"/> + <source>The OVA contains no manifest and cannot be signed!</source> + <translation>OVA Š½Šµ ŃŠ¾Š“ŠµŃŠ¶ŠøŃ Š¼Š°Š½ŠøŃŠµŃŃŠ° Šø Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠæŠ¾Š“ŠæŠøŃŠ°Š½!</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2213"/> + <source>The OVA is already signed ('%s')! (Use the --force option to force re-signing it.)</source> + <translation>OVA ŃŠ¶Šµ ŠæŠ¾Š“ŠæŠøŃŠ°Š½ ('%s')! (ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ Š¾ŠæŃŠøŃ --force, ŃŃŠ¾Š±Ń Š·Š°Š½Š¾Š²Š¾ ŠæŠ¾Š“ŠæŠøŃŠ°ŃŃ ŠµŠ³Š¾.)</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2233"/> + <source>Writing '%s' to the OVA...</source> + <translation>ŠŠ°ŠæŠøŃŃ '%s' Š² OVA...</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2243"/> + <source>RTZipTarFsStreamTruncate failed on '%s': %Rrc</source> + <translation>RTZipTarFsStreamTruncate Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2252"/> + <source>RTVfsFileSeek(hVfsFileSignature) failed: %Rrc</source> + <translation>RTVfsFileSeek(hVfsFileSignature) Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2258"/> + <source>RTVfsFsStrmAdd('%s') failed on '%s': %Rrc</source> + <translation>RTVfsFsStrmAdd('%s') Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2265"/> + <source>RTVfsFsStrmEnd failed on '%s': %Rrc</source> + <translation>RTVfsFsStrmEnd Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2301"/> + <source> Successfully decoded the PKCS#7/CMS signature...</source> + <translation> PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ Š“ŠµŠŗŠ¾Š“ŠøŃŠ¾Š²Š°Š½Š° ŃŃŠæŠµŃŠ½Š¾...</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2317"/> + <source> Successfully verified the PKCS#7/CMS signature</source> + <translation> PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ ŠæŃŠ¾Š²ŠµŃŠµŠ½Š° ŃŃŠæŠµŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2320"/> + <source>Failed to verify the PKCS#7/CMS signature: %Rrc%RTeim</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾Š²ŠµŃŠøŃŃ PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ: %Rrc%RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2324"/> + <source>RTCrPkcs7SignedData_CheckSanity failed on PKCS#7/CMS signature: %Rrc%RTeim</source> + <translation>RTCrPkcs7SignedData_CheckSanity Š·Š°Š²ŠµŃŃŠµŠ½Š° Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŠø: %Rrc%RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2329"/> + <source>PKCS#7/CMS signature inner ContentType isn't 'data' but: %s</source> + <translation>ŠŠ½ŃŃŃŠµŠ½Š½ŠµŠµ ŠæŠ¾Š»Šµ ContentType PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŠø ŃŠ²Š»ŃŠµŃŃŃ Š½Šµ Š“Š°Š½Š½ŃŠ¼Šø, Š°: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2333"/> + <source>PKCS#7/CMD signature is not 'signedData': %s</source> + <translation>PKCS#7/CMD ŠæŠ¾Š“ŠæŠøŃŃ Š½Šµ 'signedData': %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2374"/> + <source>RTCrPkcs7ContentInfo_Clone failed: %Rrc</source> + <translation>RTCrPkcs7ContentInfo_Clone Š·Š°Š²ŠµŃŃŠµŠ½ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2378"/> + <source>RTCrPkcs7ContentInfo_DecodeAsn1 failed to decode PKCS#7/CMS signature: %Rrc%RTemi</source> + <translation>RTCrPkcs7ContentInfo_DecodeAsn1 Š½Šµ ŃŠ¼Š¾Š³ Š“ŠµŠŗŠ¾Š“ŠøŃŠ¾Š²Š°ŃŃ PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ: %Rrc%RTemi</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="2409"/> + <source>Manifest is too big: %#RX64 bytes, max 4MiB</source> + <translation> + <numerusform>ŠŠ°Š½ŠøŃŠµŃŃ ŃŠ»ŠøŃŠŗŠ¾Š¼ Š±Š¾Š»ŃŃŠ¾Š¹: %#RX64 Š±Š°Š¹Ń, Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ 4MiB</numerusform> + <numerusform>ŠŠ°Š½ŠøŃŠµŃŃ ŃŠ»ŠøŃŠŗŠ¾Š¼ Š±Š¾Š»ŃŃŠ¾Š¹: %#RX64 Š±Š°Š¹ŃŠ°, Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ 4MiB</numerusform> + <numerusform>ŠŠ°Š½ŠøŃŠµŃŃ ŃŠ»ŠøŃŠŗŠ¾Š¼ Š±Š¾Š»ŃŃŠ¾Š¹: %#RX64 Š±Š°Š¹Ń, Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ 4MiB</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2434"/> + <source>RTCrStoreCertAddFromFile failed on '%s': %Rrc%#RTeim</source> + <translation>RTCrStoreCertAddFromFile Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc%#RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2440"/> + <source>RTCrStoreCreateInMem failed: %Rrc</source> + <translation>RTCrStoreCreateInMem Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="2471"/> + <source>Created PKCS#7/CMS signature: %zu bytes, %s.</source> + <translation> + <numerusform>PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ ŃŠ¾Š·Š“Š°Š½Š°: %zu Š±Š°Š¹Ń, %s.</numerusform> + <numerusform>PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ ŃŠ¾Š·Š“Š°Š½Š°: %zu Š±Š°Š¹ŃŠ°, %s.</numerusform> + <numerusform>PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŃ ŃŠ¾Š·Š“Š°Š½Š°: %zu Š±Š°Š¹Ń, %s.</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2474"/> + <source>Using SHA-1 instead of SHA-3 for the PKCS#7/CMS signature.</source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·ŃŠµŃŃŃ SHA-1 Š²Š¼ŠµŃŃŠ¾ SHA-3 Š“Š»Ń PKCS#7/CMS ŠæŠ¾Š“ŠæŠøŃŠø.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2483"/> + <source>RTCrPemWriteBlobToVfsFile failed: %Rrc</source> + <translation>RTCrPemWriteBlobToVfsFile Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2491"/> + <source>RTCrPkcs7SimpleSignSignedData failed: %Rrc%#RTeim</source> + <translation>RTCrPkcs7SimpleSignSignedData Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc%#RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2495"/> + <source>RTVfsFileReadAt failed: %Rrc</source> + <translation>RTVfsFileReadAt Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2548"/> + <source>Unsupported digest type: %s</source> + <translation>ŠŠµŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠ¹ ŃŠøŠæ Š“Š°Š¹Š“Š¶ŠµŃŃŠ°: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2557"/> + <source>Failed to create digest for %s: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š“Š°Š¹Š“Š¶ŠµŃŃ Š“Š»Ń %s: %Rrc</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="2583"/> + <source>Created OVA signature: %zu bytes, %s</source> + <translation> + <numerusform>ŠŠ¾Š“ŠæŠøŃŃ OVA ŃŠ¾Š·Š“Š°Š½Š°: %zu Š±Š°Š¹Ń, %s</numerusform> + <numerusform>ŠŠ¾Š“ŠæŠøŃŃ OVA ŃŠ¾Š·Š“Š°Š½Š°: %zu Š±Š°Š¹ŃŠ°, %s</numerusform> + <numerusform>ŠŠ¾Š“ŠæŠøŃŃ OVA ŃŠ¾Š·Š“Š°Š½Š°: %zu Š±Š°Š¹Ń, %s</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2596"/> + <source> Successfully decoded and verified the OVA signature. +</source> + <translation> Š”ŠøŠ³Š½Š°ŃŃŃŠ° OVA Š“ŠµŠŗŠ¾Š“ŠøŃŠ¾Š²Š°Š½Š° Šø ŠæŃŠ¾Š²ŠµŃŠµŠ½Š° ŃŃŠæŠµŃŠ½Š¾. +</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2627"/> + <source>Failed to write certificate to signature file: %Rrc%#RTeim</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŠøŃŠ°ŃŃ ŃŠµŃŃŠøŃŠøŠŗŠ°Ń Š² ŃŠ°Š¹Š» ŠæŠ¾Š“ŠæŠøŃŠø: %Rrc%#RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2631"/> + <source>Failed to produce signature file: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“ŠµŠ»Š°ŃŃ ŃŠ°Š¹Š» ŃŠøŠ³Š½Š°ŃŃŃŃ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2635"/> + <source>RTVfsMemFileCreate failed: %Rrc</source> + <translation>RTVfsMemFileCreate Š·Š°Š²ŠµŃŃŠµŠ½ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2638"/> + <source>Encountered a problem when validating the signature we just created: %Rrc%#RTeim +Please make sure the certificate and private key matches.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Encountered a problem when validating the signature we just created: %Rrc%#RTeim +Plase make sure the certificate and private key matches.</source> + <translation type="vanished">Š”ŃŠ¾Š»ŠŗŠ½ŃŠ»ŠøŃŃ Ń ŠæŃŠ¾Š±Š»ŠµŠ¼Š¾Š¹ ŠæŃŠø ŠæŃŠ¾Š²ŠµŃŠŗŠµ ŃŠ¾Š»ŃŠŗŠ¾ ŃŃŠ¾ ŃŠ¾Š·Š“Š°Š½Š½Š¾Š¹ ŠæŠ¾Š“ŠæŠøŃŠø: %Rrc%#RTeim +ŠŠ¾Š¶Š°Š»ŃŠ¹ŃŃŠ°, ŃŠ±ŠµŠ“ŠøŃŠµŃŃ, ŃŃŠ¾ ŃŠµŃŃŠøŃŠøŠŗŠ°Ń Šø ŠæŃŠøŠ²Š°ŃŠ½ŃŠ¹ ŠŗŠ»ŃŃ ŃŠ¾Š¾ŃŠ²ŠµŃŃŃŠ²ŃŃŃ Š“ŃŃŠ³ Š“ŃŃŠ³Ń.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2643"/> + <source>2nd RTCrPkixPubKeySignDigest call failed: %Rrc%#RTeim</source> + <translation>ŠŃŠ¾ŃŠ¾Š¹ Š²ŃŠ·Š¾Š² RTCrPkixPubKeySignDigest Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc%#RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2650"/> + <source>RTCrPkixPubKeySignDigest failed: %Rrc%#RTeim</source> + <translation>RTCrPkixPubKeySignDigest Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rrc%#RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2653"/> + <source>Failed to create digest %s: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š“Š°Š¹Š“Š¶ŠµŃŃ %s: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2717"/> + <location filename="../VBoxManageAppliance.cpp" line="2724"/> + <source>Password is given more than once.</source> + <translation>ŠŠ°ŃŠ¾Š»Ń ŃŠŗŠ°Š·Š°Š½ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2742"/> + <source>Unknown digest type: %s</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½ŃŠ¹ ŃŠøŠæ Š“Š°Š¹Š“Š¶ŠµŃŃŠ°: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2755"/> + <source>Too many intermediate certificates: max %zu</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ ŠæŃŠ¾Š¼ŠµŠ¶ŃŃŠ¾ŃŠ½ŃŃ
ŃŠµŃŃŠøŃŠøŠŗŠ°ŃŠ¾Š²: Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ %zu</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2791"/> + <source>No OVA file was specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŃŠ°Š¹Š» OVA!</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2793"/> + <source>No signing certificate (--certificate=<file>) was specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŃŠµŃŃŠøŃŠøŠŗŠ°Ń (--certificate=<ŃŠ°Š¹Š»>)!</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2795"/> + <source>No signing private key (--private-key=<file>) was specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŠæŃŠøŠ²Š°ŃŠ½ŃŠ¹ ŠŗŠ»ŃŃ (--private-key=<ŃŠ°Š¹Š»>)!</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2799"/> + <source>The specified OVA file was not found: %s</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½ ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠ°Š¹Š» OVA: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2801"/> + <source>The specified certificate file was not found: %s</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠ°Š¹Š» ŃŠµŃŃŠøŃŠøŠŗŠ°ŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2803"/> + <source>The specified private key file was not found: %s</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠ°Š¹Š» ŠæŃŠøŠ²Š°ŃŠ½Š¾Š³Š¾ ŠŗŠ»ŃŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½: %s</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2824"/> + <source>Error reading certificate from '%s': %Rrc%#RTeim</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŃŃŠµŠ½ŠøŃ ŃŠµŃŃŠøŃŠøŠŗŠ°ŃŠ° ŠøŠ· '%s': %Rrc%#RTeim</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2833"/> + <source>Successfully read the certificate and private key.</source> + <translation>Š£ŃŠæŠµŃŠ½Š¾ ŠæŃŠ¾ŃŃŠµŠ½Ń ŃŠµŃŃŠøŃŠøŠŗŠ°Ń Šø ŠæŃŠøŠ²Š°ŃŠ½ŃŠ¹ ŠŗŠ»ŃŃ.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2859"/> + <source>Successfully signed '%s'.</source> + <translation>'%s' ŠæŠ¾Š“ŠæŠøŃŠ°Š½ ŃŃŠæŠµŃŠ½Š¾.</translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2865"/> + <source>Error reading the private key from %s: %Rrc%#RTeim</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŃŃŠµŠ½ŠøŃ ŠæŃŠøŠ²Š°ŃŠ½Š¾Š³Š¾ ŠŗŠ»ŃŃŠ° ŠøŠ· %s: %Rrc%#RTeim</translation> + </message> +</context> +<context> + <name>BWControl</name> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="65"/> + <location filename="../VBoxManageBandwidthControl.cpp" line="88"/> + <source>Limit is too big +</source> + <translation>ŠŠøŠ¼ŠøŃ ŃŠ»ŠøŃŠŗŠ¾Š¼ Š±Š¾Š»ŃŃŠ¾Š¹ +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="75"/> + <source>Invalid unit suffix. Valid suffixes are: k, m, g, K, M, G +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŃŃŃŠøŠŗŃ ŠµŠ“ŠøŠ½ŠøŃŃ ŠøŠ·Š¼ŠµŃŠµŠ½ŠøŃ. ŠŠ¾ŠæŃŃŃŠøŠ¼ŃŠµ ŃŃŃŃŠøŠŗŃŃ: k, m, g, K, M, G +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="79"/> + <source>Trailing spaces in limit! +</source> + <translation>Š£ Š»ŠøŠ¼ŠøŃŠ° ŠæŃŠ¾Š±ŠµŠ»Ń Š² ŠŗŠ¾Š½ŃŠµ ŃŃŃŠ¾ŠŗŠø! +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="81"/> + <source>No digits in limit specifier +</source> + <translation>ŠŠµŃ ŃŠøŃŃ Š² ŃŠæŠµŃŠøŃŠøŠŗŠ°ŃŠ¾ŃŠµ Š»ŠøŠ¼ŠøŃŠ° +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="83"/> + <source>Invalid limit specifier +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠæŠµŃŠøŃŠøŠŗŠ°ŃŠ¾Ń Š»ŠøŠ¼ŠøŃŠ° +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="86"/> + <source>Limit cannot be negative +</source> + <translation>ŠŠøŠ¼ŠøŃ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ Š¾ŃŃŠøŃŠ°ŃŠµŠ»ŃŠ½ŃŠ¼ +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="114"/> + <source>Bandwidth group name must not be empty! +</source> + <translation>ŠŠ¼Ń Š³ŃŃŠæŠæŃ ŠæŠ¾Š»Š¾ŃŃ ŠæŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠæŃŃŃŃŠ¼! +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="174"/> + <source>Invalid bandwidth group type +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ Š³ŃŃŠæŠæŃ ŠæŠ¾Š»Š¾ŃŃ ŠæŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="318"/> + <source>Too few parameters</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š°Š»Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="320"/> + <source>Too many parameters</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="341"/> + <source>Bandwidth groups cannot be created while the VM is running +</source> + <translation>ŠŠµŠ»ŃŠ·Ń ŃŠ¾Š·Š“Š°Š²Š°ŃŃ Š³ŃŃŠæŠæŃ ŠæŠ¾Š»Š¾ŃŃ ŠæŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ ŠæŠ¾ŠŗŠ° ŃŠ°Š±Š¾ŃŠ°ŠµŃ ŠŠ +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="350"/> + <source>Bandwidth groups cannot be deleted while the VM is running +</source> + <translation>ŠŠµŠ»ŃŠ·Ń ŃŠ“Š°Š»ŃŃŃ Š³ŃŃŠæŠæŃ ŠæŠ¾Š»Š¾ŃŃ ŠæŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ ŠæŠ¾ŠŗŠ° ŃŠ°Š±Š¾ŃŠ°ŠµŃ ŠŠ +</translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="361"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> +</context> +<context> + <name>Cloud</name> + <message> + <location filename="../VBoxManageCloud.cpp" line="74"/> + <source>Parameter --provider is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --provider</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="79"/> + <source>Parameter --profile is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --profile</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="164"/> + <source>Unknown cloud instance state "%s"</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š¾Šµ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="210"/> + <location filename="../VBoxManageCloud.cpp" line="371"/> + <source>Parameter 'compartment' is empty or absent. +Trying to get the compartment from the passed cloud profile '%s' +</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ 'compartment' ŠæŃŃŃŠ¾Š¹ ŠøŠ»Šø Š¾ŃŃŃŃŃŃŠ²ŃŠµŃ. +ŠŠ¾ŠæŃŃŠŗŠ° ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠµŠŗŃŠøŃ ŠøŠ· ŠæŠµŃŠµŠ“Š°Š½Š½Š¾Š³Š¾ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŠæŃŠ¾ŃŠøŠ»Ń '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="219"/> + <location filename="../VBoxManageCloud.cpp" line="380"/> + <source>Found the compartment '%s': +</source> + <translation>ŠŠ°Š¹Š“ŠµŠ½Š° ŃŠµŠŗŃŠøŃ '%s': +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="221"/> + <location filename="../VBoxManageCloud.cpp" line="382"/> + <source>Parameter --compartment-id is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --compartment-id</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="238"/> + <source>Reply is in the form 'instance name' = 'instance id' +</source> + <translation>ŠŃŠ²ŠµŃ Š² ŃŠ¾ŃŠ¼Š°ŃŠµ 'ŠøŠ¼Ń ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ°' = 'ID ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ°' +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="247"/> + <source>Failed to list instances</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠµŃŠµŃŠøŃŠ»ŠøŃŃ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="256"/> + <source>The list of the instances for the cloud profile '%ls' +and compartment '%s': +</source> + <translation>Š”ŠæŠøŃŠ¾Šŗ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ¾Š² Š“Š»Ń Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŠæŃŠ¾ŃŠøŠ»Ń '%ls' +Šø ŃŠµŠŗŃŠøŠø '%s': +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="324"/> + <source>Unknown cloud image state "%s"</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š¾Šµ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="399"/> + <source>Reply is in the form 'image name' = 'image id' +</source> + <translation>ŠŃŠ²ŠµŃ Š² ŃŠ¾ŃŠ¼Š°ŃŠµ 'ŠøŠ¼Ń Š¾Š±ŃŠ°Š·Š°' = 'ID Š¾Š±ŃŠ°Š·Š°' +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="407"/> + <source>Failed to list images</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠµŃŠµŃŠøŃŠ»ŠøŃŃ Š¾Š±ŃŠ°Š·Ń</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="416"/> + <source>The list of the images for the cloud profile '%ls' +and compartment '%s': +</source> + <translation>Š”ŠæŠøŃŠ¾Šŗ Š¾Š±ŃŠ°Š·Š¾Š² Š“Š»Ń Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŠæŃŠ¾ŃŠøŠ»Ń '%ls' +Šø ŃŠµŠŗŃŠøŠø '%s': +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="473"/> + <location filename="../VBoxManageCloud.cpp" line="553"/> + <location filename="../VBoxManageCloud.cpp" line="747"/> + <location filename="../VBoxManageCloud.cpp" line="898"/> + <location filename="../VBoxManageCloud.cpp" line="980"/> + <location filename="../VBoxManageCloud.cpp" line="1062"/> + <location filename="../VBoxManageCloud.cpp" line="1159"/> + <location filename="../VBoxManageCloud.cpp" line="1236"/> + <location filename="../VBoxManageCloud.cpp" line="1342"/> + <location filename="../VBoxManageCloud.cpp" line="1537"/> + <location filename="../VBoxManageCloud.cpp" line="1622"/> + <location filename="../VBoxManageCloud.cpp" line="1713"/> + <location filename="../VBoxManageCloud.cpp" line="1808"/> + <source>Empty command parameter list, show help. +</source> + <translation>Š”ŠæŠøŃŠ¾Šŗ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š² ŠŗŠ¾Š¼Š°Š½Š“Ń ŠæŃŃŃ, Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŠµ ŃŠæŃŠ°Š²ŠŗŠø. +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="663"/> + <source>Warning!!! Public SSH key doesn't present in the passed arguments... +</source> + <translation>ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ!!! ŠŃŠ±Š»ŠøŃŠ½ŃŠ¹ SSH ŠŗŠ»ŃŃ Š½Šµ ŠæŃŠµŠ“ŃŃŠ°Š²Š»ŠµŠ½ Š² ŠæŠµŃŠµŠ“Š°Š½Š½ŃŃ
Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ°Ń
... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="666"/> + <source>Parameters --image-id and --boot-volume-id are mutually exclusive. Only one of them must be presented.</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃŃ --image-id Šø --boot-volume-id Š²Š·Š°ŠøŠ¼Š¾ŠøŃŠŗŠ»ŃŃŠ°ŃŃŠøŠµ. ŠŠ¾Š¶ŠµŃ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŠøŠ· Š½ŠøŃ
.</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="670"/> + <source>Missing parameter --image-id or --boot-volume-id. One of them must be presented.</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ --image-id Šø --boot-volume-id. ŠŠ“ŠøŠ½ ŠøŠ· Š½ŠøŃ
Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½.</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="692"/> + <source>Checking the cloud image with id '%s'... +</source> + <translation>ŠŃŠ¾Š²ŠµŃŠŗŠ° Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° Ń ID '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="700"/> + <source>Checking the cloud image failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾Š²ŠµŃŠøŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ Š¾Š±ŃŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="706"/> + <source>Creating cloud instance with name '%s' from the image '%s'... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s' ŠøŠ· Š¾Š±ŃŠ°Š·Š° '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="709"/> + <source>Creating cloud instance with name '%s' from the boot volume '%s'... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s' ŠøŠ· Š·Š°Š³ŃŠ°Š·ŃŠ·Š¾ŃŠ½Š¾Š³Š¾ ŃŠ¾Š¼Š° '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="715"/> + <source>Creating cloud instance failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="718"/> + <source>Cloud instance was created successfully +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ ŃŠ¾Š·Š“Š°Š½ ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="762"/> + <location filename="../VBoxManageCloud.cpp" line="913"/> + <location filename="../VBoxManageCloud.cpp" line="995"/> + <location filename="../VBoxManageCloud.cpp" line="1077"/> + <location filename="../VBoxManageCloud.cpp" line="1386"/> + <location filename="../VBoxManageCloud.cpp" line="1728"/> + <source>Duplicate parameter: --id</source> + <translation>ŠŃŠ±Š»ŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --id</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="766"/> + <location filename="../VBoxManageCloud.cpp" line="917"/> + <location filename="../VBoxManageCloud.cpp" line="999"/> + <location filename="../VBoxManageCloud.cpp" line="1081"/> + <location filename="../VBoxManageCloud.cpp" line="1390"/> + <location filename="../VBoxManageCloud.cpp" line="1732"/> + <source>Empty parameter: --id</source> + <translation>ŠŃŃŃŠ¾Š¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --id</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="787"/> + <location filename="../VBoxManageCloud.cpp" line="938"/> + <location filename="../VBoxManageCloud.cpp" line="1020"/> + <location filename="../VBoxManageCloud.cpp" line="1102"/> + <location filename="../VBoxManageCloud.cpp" line="1439"/> + <location filename="../VBoxManageCloud.cpp" line="1754"/> + <source>Missing parameter: --id</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --id</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="795"/> + <source>Getting information about cloud instance with id %s... +</source> + <translation>ŠŠ¾Š»ŃŃŠµŠ½ŠøŠµ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŠø Š¾Š± Š¾Š±Š»Š°ŃŠ½Š¾Š¼ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠµ Ń ID %s... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="796"/> + <source>Reply is in the form 'setting name' = 'value' +</source> + <translation>ŠŃŠ²ŠµŃ Š² ŃŠ¾ŃŠ¼Š°ŃŠµ 'Š½Š°Š·Š²Š°Š½ŠøŠµ Š½Š°ŃŃŃŠ¾Š¹ŠŗŠø' = 'Š·Š½Š°ŃŠµŠ½ŠøŠµ' +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="817"/> + <source>Getting information about cloud instance failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾Š± Š¾Š±Š»Š°ŃŠ½Š¾Š¼ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠµ</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="819"/> + <source>Cloud instance info (provider '%s'): +</source> + <translation>ŠŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾Š± Š¾Š±Š»Š°ŃŠ½Š¾Š¼ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠµ (ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ '%s'): +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="830"/> + <source>Availability domain = %ls +</source> + <translation>ŠŠ¾Š¼ŠµŠ½ Š“Š¾ŃŃŃŠæŠ½Š¾ŃŃŠø = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="830"/> + <source>Availability domain wasn't found +</source> + <translation>ŠŠ¾Š¼ŠµŠ½ Š“Š¾ŃŃŃŠæŠ½Š¾ŃŃŠø Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="831"/> + <source>Instance displayed name = %ls +</source> + <translation>ŠŃŠ¾Š±ŃŠ°Š¶Š°ŠµŠ¼Š¾Šµ ŠøŠ¼Ń ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="831"/> + <source>Instance displayed name wasn't found +</source> + <translation>ŠŃŠ¾Š±ŃŠ°Š¶Š°ŠµŠ¼Š¾Šµ ŠøŠ¼Ń ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="832"/> + <source>Instance state = %ls +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="832"/> + <source>Instance state wasn't found +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="833"/> + <source>Instance Id = %ls +</source> + <translation>ID ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="833"/> + <source>Instance Id wasn't found +</source> + <translation>ID ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="834"/> + <source>Instance name = %ls +</source> + <translation>ŠŠ¼Ń ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="834"/> + <source>Instance name wasn't found +</source> + <translation>ŠŠ¼Ń ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="835"/> + <source>Bootable image Id = %ls +</source> + <translation>ID Š·Š°Š³ŃŃŠ·Š¾ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="836"/> + <source>Image Id whom the instance is booted up wasn't found +</source> + <translation>ID Š¾Š±ŃŠ°Š·Š°, Š¾ŃŠŗŃŠ“Š° Š·Š°Š³ŃŃŠ¶Š°ŠµŃŃŃ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ,Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="837"/> + <source>Shape of the instance = %ls +</source> + <translation>Š¤Š¾ŃŠ¼Š° ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="838"/> + <source>The shape of the instance wasn't found +</source> + <translation>Š¤Š¾ŃŠ¼Š° ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½Š° +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="839"/> + <source>Type of guest OS = %ls +</source> + <translation>Š¢ŠøŠæ Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="839"/> + <source>Type of guest OS wasn't found +</source> + <translation>Š¢ŠøŠæ Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="840"/> + <source>RAM = %ls MB +</source> + <translation>RAM = %ls MB +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="840"/> + <source>Value for RAM wasn't found +</source> + <translation>Š Š°Š·Š¼ŠµŃ RAM Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="841"/> + <source>CPUs = %ls +</source> + <translation>Š¦ŠŠ£ = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="841"/> + <source>Numbers of CPUs weren't found +</source> + <translation>ŠŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ Š¦ŠŠ£ Š½Šµ Š½Š°Š¹Š“ŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="842"/> + <source>Instance public IP = %ls +</source> + <translation>ŠŃŠ±Š»ŠøŃŠ½ŃŠ¹ IP ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="842"/> + <source>Public IP wasn't found +</source> + <translation>ŠŃŠ±Š»ŠøŃŠ½ŃŠ¹ IP Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="843"/> + <source>Free-form tags or metadata weren't found +</source> + <translation>Š¢ŠµŠ³Šø ŠøŠ»Šø Š¼ŠµŃŠ°Š“Š°Š½Š½ŃŠµ ŠæŃŠ¾ŠøŠ·Š²Š¾Š»ŃŠ½Š¾Š¹ ŃŠ¾ŃŠ¼Ń Š½Šµ Š½Š°Š¹Š“ŠµŠ½Ń +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="844"/> + <source>Cloud-init script wasn't found +</source> + <translation>Š”ŠŗŃŠøŠæŃ ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·Š°ŃŠøŠø Š¾Š±Š»Š°ŠŗŠ° Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="946"/> + <source>Starting cloud instance with id %s... +</source> + <translation>ŠŠ°ŠæŃŃŠŗ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Ń ID %s... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="953"/> + <source>Starting the cloud instance failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŃŃŃŠøŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="956"/> + <source>Cloud instance with id %s (provider = '%s', profile = '%s') was started +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ Ń ID %s (ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ = '%s', ŠæŃŠ¾ŃŠøŠ»Ń = '%s') Š·Š°ŠæŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1028"/> + <source>Pausing cloud instance with id %s... +</source> + <translation>ŠŃŠøŠ¾ŃŃŠ°Š½Š¾Š²ŠŗŠ° Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Ń ID %s... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1035"/> + <source>Pause the cloud instance failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠøŠ¾ŃŃŠ°Š½Š¾Š²ŠøŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1038"/> + <source>Cloud instance with id %s (provider = '%s', profile = '%s') was paused +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ Ń ID %s (ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ = '%s', ŠæŃŠ¾ŃŠøŠ»Ń = '%s') ŠæŃŠøŠ¾ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1111"/> + <source>Terminating cloud instance with id %s... +</source> + <translation>ŠŠ°Š²ŠµŃŃŠµŠ½ŠøŠµ ŃŠ°Š±Š¾ŃŃ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° Ń ID %s... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1118"/> + <source>Termination the cloud instance failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š²ŠµŃŃŠøŃŃ ŃŠ°Š±Š¾ŃŃ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1121"/> + <source>Cloud instance with id %s (provider = '%s', profile = '%s') was terminated +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ Ń ID %s (ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ = '%s', ŠæŃŠ¾ŃŠøŠ»Ń = '%s') Š·Š°Š²ŠµŃŃŠøŠ» ŃŠ°Š±Š¾ŃŃ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1293"/> + <source>Conflicting parameters: --instance-id and --object-name can't be used together. Choose one.</source> + <translation>ŠŠ¾Š½ŃŠ»ŠøŠŗŃŃŃŃŠøŠµ ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ: --instance-id Šø --object-name Š½Šµ Š¼Š¾Š³ŃŃ Š±ŃŃŃ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½Ń Š²Š¼ŠµŃŃŠµ. ŠŃŠ±ŠµŃŠøŃŠµ Š¾Š“ŠøŠ½.</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1302"/> + <source>Creating cloud image with name '%s' from the instance '%s'... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s' ŠøŠ· ŃŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃŠ° '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1305"/> + <source>Creating cloud image with name '%s' from the object '%s' in the bucket '%s'... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s' ŠøŠ· Š¾Š±ŃŠµŠŗŃŠ° '%s' Š² ŠŗŠ¾ŃŠ·ŠøŠ½Šµ '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1313"/> + <source>Creating cloud image failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ Š¾Š±ŃŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1316"/> + <source>Cloud image was created successfully +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ Š¾Š±ŃŠ°Š· ŃŠ¾Š·Š“Š°Š½ ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1362"/> + <source>Duplicate parameter: --bucket-name</source> + <translation>ŠŃŠ±Š»ŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --bucket-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1366"/> + <source>Empty parameter: --bucket-name</source> + <translation>ŠŃŃŃŠ¾Š¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --bucket-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1374"/> + <source>Duplicate parameter: --object-name</source> + <translation>ŠŃŠ±Š»ŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --object-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1378"/> + <source>Empty parameter: --object-name</source> + <translation>ŠŃŃŃŠ¾Š¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --object-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1398"/> + <source>Duplicate parameter: --display-name</source> + <translation>ŠŃŠ±Š»ŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --display-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1402"/> + <source>Empty parameter: --display-name</source> + <translation>ŠŃŃŃŠ¾Š¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --display-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1410"/> + <source>Duplicate parameter: --launch-mode</source> + <translation>ŠŃŠ±Š»ŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --launch-mode</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1414"/> + <source>Empty parameter: --launch-mode</source> + <translation>ŠŃŃŃŠ¾Š¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --launch-mode</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1444"/> + <source>Missing parameter: --bucket-name</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: --bucket-name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1464"/> + <source>Exporting image '%s' to the Cloud with name '%s'... +</source> + <translation>ŠŠŗŃŠæŠ¾ŃŃ Š¾Š±ŃŠ°Š·Š° '%s' Š² Š¾Š±Š»Š°ŠŗŠ¾ Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1467"/> + <source>Exporting image '%s' to the Cloud with default name +</source> + <translation>ŠŠŗŃŠæŠ¾ŃŃ Š¾Š±ŃŠ°Š·Š° '%s' Š² Š¾Š±Š»Š°ŠŗŠ¾ Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1495"/> + <source>Image %s was found +</source> + <translation>ŠŠ±ŃŠ°Š· %s Š½Šµ Š½Š°Š¹Š“ŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1502"/> + <source>Process of exporting the image to the Cloud was interrupted. The image wasn't found. +</source> + <translation>ŠŃŠ¾ŃŠµŃŃ ŃŠŗŃŠæŠ¾ŃŃŠ° Š¾Š±ŃŠ°Š·Š° Š² Š¾Š±Š»Š°ŠŗŠ¾ ŠæŃŠµŃŠ²Š°Š½. ŠŠ±ŃŠ°Š· Š½Šµ Š½Š°Š¹Š“ŠµŠ½. +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1511"/> + <source>Export the image to the Cloud failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠŗŃŠæŠ¾ŃŃŠøŃŠ¾Š²Š°ŃŃ Š¾Š±ŃŠ°Š· Š² Š¾Š±Š»Š°ŠŗŠ¾</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1514"/> + <source>Export the image to the Cloud was successfull +</source> + <translation>ŠŠŗŃŠæŠ¾ŃŃ Š¾Š±ŃŠ°Š·Š° Š² Š¾Š±Š»Š°ŠŗŠ¾ Š·Š°ŠŗŠ¾Š½ŃŠøŠ»ŃŃ ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1587"/> + <source>Creating an object '%s' from the cloud image '%s'... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±ŃŠµŠŗŃŠ° '%s' ŠøŠ· Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1594"/> + <source>Cloud image import failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠøŠ¼ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°ŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ Š¾Š±ŃŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1598"/> + <source>Cloud image was imported successfully. Find the downloaded object with the name %s in the system temp folder (find the possible environment variables like TEMP, TMP and etc.) +</source> + <translation>ŠŠ¼ŠæŠ¾ŃŃ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° Š·Š°Š²ŠµŃŃŠµŠ½ ŃŃŠæŠµŃŠ½Š¾. ŠŠ°Š¹Š“ŠøŃŠµ Š·Š°Š³ŃŃŠ¶ŠµŠ½Š½ŃŠ¹ Š¾Š±ŃŠµŠŗŃ Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ %s Š² ŃŠøŃŃŠµŠ¼Š½Š¾Š¹ ŠæŠ°ŠæŠŗŠµ Š“Š»Ń Š²ŃŠµŠ¼ŠµŠ½Š½ŃŃ
ŃŠ°Š¹Š»Š¾Š² (ŠæŠ¾ŠøŃŠøŃŠµ Š²Š¾Š·Š¼Š¾Š¶Š½ŃŠµ ŠæŠµŃŠµŠ¼ŠµŠ½Š½ŃŠµ Š¾ŠŗŃŃŠ¶ŠµŠ½ŠøŃ Š½Š°ŠæŠ¾Š“Š¾Š±ŠøŠµ TEMP, TMP Šø ŃŠ°Šŗ Š“Š°Š»ŠµŠµ.) +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1658"/> + <source>Getting information about the cloud image with id '%s'... +</source> + <translation>ŠŠ¾Š»ŃŃŠµŠ½ŠøŠµ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŠø Š¾Š± Š¾Š±Š»Š°ŃŠ½Š¾Š¼ Š¾Š±ŃŠ°Š·Šµ Ń ID '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1664"/> + <source>Reply is in the form 'image property' = 'value' +</source> + <translation>ŠŃŠ²ŠµŃ Š² ŃŠ¾ŃŠ¼Š°ŃŠµ 'ŃŠ²Š¾Š¹ŃŃŠ²Š¾ Š¾Š±ŃŠ°Š·Š°' = 'Š·Š½Š°ŃŠµŠ½ŠøŠµ' +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1672"/> + <source>Getting information about the cloud image failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾Š± Š¾Š±Š»Š°ŃŠ½Š¾Š¼ Š¾Š±ŃŠ°Š·Šµ</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1678"/> + <source>General information about the image: +</source> + <translation>ŠŠ±ŃŠ°Ń ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾Š± Š¾Š±ŃŠ°Š·Šµ: +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1763"/> + <source>Deleting cloud image with id %s... +</source> + <translation>Š£Š“Š°Š»ŠµŠ½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š³Š¾ Š¾Š±ŃŠ°Š·Š° Ń ID %s... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1770"/> + <source>Deleting cloud image failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ Š¾Š±Š»Š°ŃŠ½ŃŠ¹ Š¾Š±ŃŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1773"/> + <source>Cloud image was deleted successfully +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ Š¾Š±ŃŠ°Š· ŃŠ“Š°Š»ŠµŠ½ ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1956"/> + <location filename="../VBoxManageCloud.cpp" line="2007"/> + <location filename="../VBoxManageCloud.cpp" line="2081"/> + <location filename="../VBoxManageCloud.cpp" line="2128"/> + <source>Missing --name parameter</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --name</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1958"/> + <source>Missing --network-id parameter</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --network-id</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1970"/> + <source>Cloud network was created successfully +</source> + <translation>ŠŠ±Š»Š°ŃŠ½Š°Ń ŃŠµŃŃ ŃŠ¾Š·Š“Š°Š½Š° ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2015"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2018"/> + <source>State: %s +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2018"/> + <source>Enabled</source> + <translation>ŠŠŗŠ»ŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2018"/> + <source>Disabled</source> + <translation>ŠŃŠŗŠ»ŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2021"/> + <source>CloudProvider: %ls +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2024"/> + <source>CloudProfile: %ls +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŠæŃŠ¾ŃŠøŠ»Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2027"/> + <source>CloudNetworkId: %ls +</source> + <translation>ID Š¾Š±Š»Š°ŃŠ½Š¾Š¹ ŃŠµŃŠø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2029"/> + <source>VBoxNetworkName: %ls + +</source> + <translation>ŠŠ¼Ń ŃŠµŃŠø VBox: %ls + +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2091"/> + <source>Cloud network %ls was updated successfully +</source> + <translation>ŠŠ±Š»Š°ŃŠ½Š°Ń ŃŠµŃŃ %ls Š¾Š±Š½Š¾Š²Š»ŠµŠ½Š° ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2141"/> + <source>Cloud network %ls was deleted successfully +</source> + <translation>ŠŠ±Š»Š°ŃŠ½Š°Ń ŃŠµŃŃ %ls ŃŠ“Š°Š»ŠµŠ½Š° ŃŃŠæŠµŃŠ½Š¾ +</translation> + </message> + <message> + <source>Failed to compose path to the unattended installer script templates (%Rrc)</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š±ŃŠ°ŃŃ ŠæŃŃŃ Š“Š»Ń ŃŠ°Š±Š»Š¾Š½Š¾Š² ŃŠŗŃŠøŠæŃŠ¾Š² unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ° (%Rrc)</translation> + </message> + <message> + <source>Failed to obtain system properties.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ²Š¾Š¹ŃŃŠ²Š° ŃŠøŃŃŠµŠ¼Ń.</translation> + </message> + <message> + <source>Failed to obtain proxy mode.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠµŠ¶ŠøŠ¼ ŠæŃŠ¾ŠŗŃŠø.</translation> + </message> + <message> + <source>Failed to obtain proxy URL.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ URL ŠæŃŠ¾ŠŗŃŠø.</translation> + </message> + <message> + <source>Failed to get system proxy for https://dl.fedoraproject.org. Will use direct connection.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠøŃŃŠµŠ¼Š½ŃŠ¹ ŠæŃŠ¾ŠŗŃŠø Š“Š»Ń https://dl.fedoraproject.org. ŠŃŠ“ŠµŃ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½Š¾ ŠæŃŃŠ¼Š¾Šµ ŃŠ¾ŠµŠ“ŠøŠ½ŠµŠ½ŠøŠµ.</translation> + </message> + <message> + <source>Failed to obtain default machine folder.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠæŠ°ŠæŠŗŃ Š¼Š°ŃŠøŠ½Ń ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ.</translation> + </message> + <message> + <source>Failed to obtain default guest additions ISO path.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠæŃŃŃ ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ Šŗ ISO ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”.</translation> + </message> + <message> + <source>The default guest additions ISO path is empty nor it is provided as --guest-additions-iso parameter. Cannot proceed without it.</source> + <translation type="vanished">ŠŃŃŃ ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ Šŗ ISO ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” ŠæŃŃŃ ŠøŠ»Šø Š½Šµ ŃŠŗŠ°Š·Š°Š½ ŃŠµŃŠµŠ· --guest-additions-iso parameter. ŠŃŠ¾Š“Š¾Š»Š¶ŠµŠ½ŠøŠµ Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š±ŠµŠ· ŃŃŠ¾Š³Š¾.</translation> + </message> + <message> + <source>Failed to compose a path to the local gateway image (%Rrc)</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š±ŃŠ°ŃŃ ŠæŃŃŃ Šŗ Š¾Š±ŃŠ°Š·Ń Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š° (%Rrc)</translation> + </message> + <message> + <source>Local gateway image already exists, skipping image preparation step. +</source> + <translation type="vanished">ŠŠ±ŃŠ°Š· Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š° ŃŠ¶Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ, ŠæŃŠ¾ŠæŃŃŠŗ ŃŠ°Š³Š° ŠæŠ¾Š“Š³Š¾ŃŠ¾Š²ŠŗŠø Š¾Š±ŃŠ°Š·Š°. +</translation> + </message> + <message> + <source>Preparing unattended install of temporary local gateway machine from %ls... +</source> + <translation type="vanished">ŠŠ¾Š“Š³Š¾ŃŠ¾Š²ŠŗŠ° unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŠø Š¼Š°ŃŠøŠ½Ń Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š³Š¾ Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š° ŠøŠ· %ls... +</translation> + </message> + <message> + <source>Failed to open %ls.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŃŃŃŃ %ls.</translation> + </message> + <message> + <source>Failed to create '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ '%ls'.</translation> + </message> + <message> + <source>Failed to apply defaults to '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠøŠ¼ŠµŠ½ŠøŃŃ Š½Š°ŃŃŃŠ¾Š¹ŠŗŠø ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ Šŗ '%ls'.</translation> + </message> + <message> + <source>Failed to adjust CPU count for '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š“ŃŃŃŠ¾ŠøŃŃ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ Š¦ŠŠ£ Š“Š»Ń '%ls'.</translation> + </message> + <message> + <source>Failed to adjust memory size for '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š“ŃŃŃŠ¾ŠøŃŃ ŃŠ°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø Š“Š»Ń '%ls'.</translation> + </message> + <message> + <source>Failed to set attachment type for the second network adapter.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŃŃŠ°Š½Š¾Š²ŠøŃŃ ŃŠøŠæ ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŃ Š“Š»Ń Š²ŃŠ¾ŃŠ¾Š³Š¾ ŃŠµŃŠµŠ²Š¾Š³Š¾ Š°Š“Š°ŠæŃŠµŃŠ°.</translation> + </message> + <message> + <source>Failed to disable the audio adapter.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŠ»ŃŃŠøŃŃ Š°ŃŠ“ŠøŠ¾ Š°Š“Š°ŠæŃŠµŃ.</translation> + </message> + <message> + <source>Failed to register '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŃŠµŠ³ŠøŃŃŃŠøŃŠ¾Š²Š°ŃŃ '%ls'.</translation> + </message> + <message> + <source>Failed to create %ls.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ %ls.</translation> + </message> + <message> + <source>Failed to create base storage for local gateway image.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š±Š°Š·Š¾Š²Š¾Šµ Ń
ŃŠ°Š½ŠøŠ»ŠøŃŠµ Š“Š»Ń Š¾Š±ŃŠ°Š·Š° Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š°.</translation> + </message> + <message> + <source>Failed to lock '%ls' for modifications.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š±Š»Š¾ŠŗŠøŃŠ¾Š²Š°ŃŃ '%ls' Š“Š»Ń ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŃ.</translation> + </message> + <message> + <source>Failed to obtain a mutable machine.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ·Š¼ŠµŠ½ŃŠµŠ¼ŃŃ Š¼Š°ŃŠøŠ½Ń.</translation> + </message> + <message> + <source>Failed to attach HD to '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š“ŠŗŠ»ŃŃŠøŃŃ Š¶ŠµŃŃŠŗŠøŠ¹ Š“ŠøŃŠŗ Šŗ '%ls'.</translation> + </message> + <message> + <source>Failed to attach ISO to '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š“ŠŗŠ»ŃŃŠøŃŃ ISO Šŗ '%ls'.</translation> + </message> + <message> + <source>Failed to save '%ls' settings.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Ń
ŃŠ°Š½ŠøŃŃ Š½Š°ŃŃŃŠ¾Š¹ŠŗŠø '%ls'.</translation> + </message> + <message> + <source>Failed to create unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾Ń.</translation> + </message> + <message> + <source>Failed to set machine for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ Š¼Š°ŃŠøŠ½Ń Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to set user for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»Ń Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to set password for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»Ń Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to set full user name for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŠæŠ¾Š»Š½Š¾Šµ ŠøŠ¼Ń ŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»Ń Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to enable guest addtions for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŠŗŠ»ŃŃŠøŃŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to set guest addtions ISO path for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŠæŃŃŃ Šŗ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃŠ¼ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to set script template for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŃŠ°Š±Š»Š¾Š½ ŃŠŗŃŠøŠæŃŠ° Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to set post install script template for the unattended installer.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŃŠ°Š»Š¾Š½ post-install ŃŠŗŃŠøŠæŃŠ° Š“Š»Ń unattended ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ°.</translation> + </message> + <message> + <source>Failed to prepare unattended installation.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š“Š³Š¾ŃŠ¾Š²ŠøŃŃ unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŃ.</translation> + </message> + <message> + <source>Failed to construct media for unattended installation.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š±ŃŠ°ŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń Š“Š»Ń unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŠø.</translation> + </message> + <message> + <source>Failed to reconfigure %ls for unattended installation.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠµŃŠµŠŗŠ¾Š½ŃŠøŠ³ŃŃŠøŃŠ¾Š²Š°ŃŃ %ls Š“Š»Ń unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŠø.</translation> + </message> + <message> + <source> %32s = failed: %Rhrc +</source> + <translation type="vanished"> %32s = Š·Š°Š²ŠµŃŃŠµŠ½Š¾ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rhrc +</translation> + </message> + <message> + <source>Performing unattended install of temporary local gateway... +</source> + <translation type="vanished">ŠŃŠ¾ŠøŠ·Š²Š¾Š“ŠøŃŃŃ unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŠ° Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š³Š¾ Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š°... +</translation> + </message> + <message> + <source>Failed to launch '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŃŃŃŠøŃŃ '%ls'.</translation> + </message> + <message> + <source>Failed to get machine state.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ Š¼Š°ŃŠøŠ½Ń.</translation> + </message> + <message> + <source>Temporary local gateway VM has aborted.</source> + <translation type="vanished">ŠŠ Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š³Š¾ Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š° ŠæŃŠµŃŠ²Š°Š½Š°.</translation> + </message> + <message> + <source>Timed out (40min) while waiting for unattended install to finish.</source> + <translation type="vanished">ŠŃŠµŠ²ŃŃŠµŠ½Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ (40 Š¼ŠøŠ½) Š·Š°Š²ŠµŃŃŠµŠ½ŠøŃ unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŠø.</translation> + </message> + <message> + <source><byte value="xd"/>Done. +</source> + <translation type="vanished"><byte value="xd"/>Š”Š“ŠµŠ»Š°Š½Š¾. +</translation> + </message> + <message> + <source>Detaching local gateway image... +</source> + <translation type="vanished">ŠŃŠŗŠ»ŃŃŠµŠ½ŠøŠµ Š¾Š±ŃŠ°Š·Š° Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š°... +</translation> + </message> + <message> + <source>Failed to detach HD to '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŠ»ŃŃŠøŃŃ Š¶ŠµŃŃŠŗŠøŠ¹ Š“ŠøŃŠŗ Š¾Ń '%ls'.</translation> + </message> + <message> + <source>Unregistering temporary local gateway machine... +</source> + <translation type="vanished">ŠŃŠ¼ŠµŠ½Š° ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŠø Š¼Š°ŃŠøŠ½Ń Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š³Š¾ Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š°... +</translation> + </message> + <message> + <source>Failed to unregister '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠ¼ŠµŠ½ŠøŃŃ ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŃ '%ls'.</translation> + </message> + <message> + <source>Failed to delete config for '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ Š“Š»Ń '%ls'.</translation> + </message> + <message> + <source>Making local gateway image immutable... +</source> + <translation type="vanished">ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŃŠ»ŃŠ·Š° Š² Š½ŠµŠøŠ·Š¼ŠµŠ½ŃŠµŠ¼ŃŠ¹... +</translation> + </message> + <message> + <source>Failed to open '%ls'.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŃŃŃŃ '%ls'.</translation> + </message> + <message> + <source>Failed to make '%ls' immutable.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“ŠµŠ»Š°ŃŃ '%ls' Š½ŠµŠøŠ·Š¼ŠµŠ½ŃŠµŠ¼ŃŠ¼.</translation> + </message> + <message> + <source>Missing --local-gateway-iso parameter</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --local-gateway-iso</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2209"/> + <source>Setting up tunnel network in the cloud... +</source> + <translation>Š£ŃŃŠ°Š½Š¾Š²ŠŗŠ° ŃŃŠ½Š½ŠµŠ»ŃŠ½Š¾Š¹ ŃŠµŃŠø Š² Š¾Š±Š»Š°ŠŗŠµ... +</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2235"/> + <source>Setting up cloud network environment failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŃŃŠ°Š½Š¾Š²ŠøŃŃ Š¾ŠŗŃŃŠ¶ŠµŠ½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š¹ ŃŠµŃŠø</translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2239"/> + <source>Cloud network environment was set up successfully. Tunnel network id is: %ls +</source> + <translation>ŠŠŗŃŃŠ¶ŠµŠ½ŠøŠµ Š¾Š±Š»Š°ŃŠ½Š¾Š¹ ŃŠµŃŠø ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š¾ ŃŃŠæŠµŃŠ½Š¾. ID ŃŃŠ½Š½ŠµŠ»ŃŠ½Š¾Š¹ ŃŠµŃŠø: %ls +</translation> + </message> +</context> +<context> + <name>CloudMachine</name> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="172"/> + <source>cloud: no providers available</source> + <translation>Š¾Š±Š»Š°ŠŗŠ¾: Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š¾ Š½Šø Š¾Š“Š½Š¾Š³Š¾ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="178"/> + <source>cloud: multiple providers available, '--provider' option is required</source> + <translation>Š¾Š±Š»Š°ŠŗŠ¾: Š“Š¾ŃŃŃŠæŠ½Š¾ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃŠ¾Š², ŃŃŠµŠ±ŃŠµŃŃŃ Š¾ŠæŃŠøŃ '--provider'</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="231"/> + <source>cloud: no profiles exist</source> + <translation>Š¾Š±Š»Š°ŠŗŠ¾: Š½Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ Š½Šø Š¾Š“Š½Š¾Š³Š¾ ŠæŃŠ¾ŃŠøŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="237"/> + <source>cloud: multiple profiles exist, '--profile' option is required</source> + <translation>Š¾Š±Š»Š°ŠŗŠ¾: ŃŃŃŠµŃŃŠ²ŃŠµŃ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŠæŃŠ¾ŃŠøŠ»ŠµŠ¹, ŃŃŠµŠ±ŃŠµŃŃŃ Š¾ŠæŃŠøŃ '--profile'</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="363"/> + <source>ambiguous name: %ls and %ls</source> + <translation>Š½ŠµŠ¾Š“Š½Š¾Š·Š½Š°ŃŠ½Š¾Šµ ŠøŠ¼Ń: %ls Šø %ls</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="419"/> + <source>only one machine can be specified</source> + <translation>Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½Š° ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“Š½Š° Š¼Š°ŃŠøŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="467"/> + <source>not a valid uuid: %s</source> + <translation>Š½ŠµŠ“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŃŠ½ŃŠ¹ uuid: %s</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="530"/> + <source>machine not specified</source> + <translation>Š¼Š°ŃŠøŠ½Š° Š½Šµ ŃŠŗŠ°Š·Š°Š½Š°</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="536"/> + <source>machine name is empty</source> + <translation>ŠøŠ¼Ń Š¼Š°ŃŠøŠ½Ń ŠæŃŃŃŠ¾</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="547"/> + <source>unable to find machine with id %s</source> + <translation>Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø Š¼Š°ŃŠøŠ½Ń Ń ID %s</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="557"/> + <source>unable to find machine with name %s</source> + <translation>Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø Š¼Š°ŃŠøŠ½Ń Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ %s</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="567"/> + <source>unable to find machine %s</source> + <translation>Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø Š¼Š°ŃŠøŠ½Ń %s</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="639"/> + <source>cloud machine: RTGetOptInit: %Rra</source> + <translation>Š¾Š±Š»Š°ŃŠ½Š°Ń Š¼Š°ŃŠøŠ½Š°: RTGetOptInit: %Rra</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="654"/> + <location filename="../VBoxManageCloudMachine.cpp" line="789"/> + <source>Invalid sub-command: %s</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°: %s</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="700"/> + <source>cloud machine: internal error: %d</source> + <translation>Š¾Š±Š»Š°ŃŠ½Š°Ń Š¼Š°ŃŠøŠ½Š°: Š²Š½ŃŃŃŠµŠ½Š½ŃŃ Š¾ŃŠøŠ±ŠŗŠ°: %d</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="705"/> + <source>cloud machine: command required +Try '--help' for more information.</source> + <translation>Š¾Š±Š»Š°ŃŠ½Š°Ń Š¼Š°ŃŠøŠ½Š°: ŃŃŠµŠ±ŃŠµŃŃŃ ŠŗŠ¾Š¼Š°Š½Š“Š° +ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ '--help' Š“Š»Ń Š“ŠµŃŠ°Š»ŃŠ½Š¾Š¹ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŠø.</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="757"/> + <source>cloud machine list: unexpected machine argument</source> + <translation>ŃŠæŠøŃŠ¾Šŗ Š¾Š±Š»Š°ŃŠ½ŃŃ
Š¼Š°ŃŠøŠ½: Š½ŠµŠ¾Š¶ŠøŠ“Š°Š½Š½ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Š¼Š°ŃŠøŠ½Ń</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="765"/> + <source>cloud machine list: RTGetOptInit: %Rra</source> + <translation>ŃŠæŠøŃŠ¾Šŗ Š¾Š±Š»Š°ŃŠ½ŃŃ
Š¼Š°ŃŠøŠ½: RTGetOptInit: %Rra</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="987"/> + <source>machine is not accessible</source> + <translation>Š¼Š°ŃŠøŠ½Š° Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1017"/> + <source>State: Invalid (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1021"/> + <source>State: Provisioning (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŠ¾Š“Š³Š¾ŃŠ¾Š²ŠŗŠ° (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1025"/> + <source>State: Running (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: Š Š°Š±Š¾ŃŠ°ŠµŃ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1029"/> + <source>State: Starting (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŠ°ŠæŃŃŠŗŠ°ŠµŃŃŃ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1033"/> + <source>State: Stopping (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŃŃŠ°Š½Š°Š²Š»ŠøŠ²Š°ŠµŃŃŃ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1037"/> + <source>State: Stopped (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š° (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1041"/> + <source>State: CreatingImage (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: Š”Š¾Š·Š“Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1045"/> + <source>State: Terminating (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŠ°Š²ŠµŃŃŠµŠ½ŠøŠµ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1049"/> + <source>State: Terminated (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŠ°Š²ŠµŃŃŠµŠ½Š¾ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1053"/> + <source>State: Unknown state (%RU32) +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š¾Šµ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ (%RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1062"/> + <source>null details</source> + <translation>ŠæŠ¾Š“ŃŠ¾Š±Š½Š°Ń ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾ŃŃŃŃŃŃŠ²ŃŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1109"/> + <source>%ls: unable to convert to boolean value +</source> + <translation>%ls: Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ Š² Š±ŃŠ»ŠµŠ²Š¾ Š·Š½Š°ŃŠµŠ½ŠøŠµ +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1135"/> + <source>%ls: unable to convert to string value +</source> + <translation>%ls: Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ Š² ŃŃŃŠ¾ŠŗŠ¾Š²Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1177"/> + <source>%ls: unable to convert to integer value +</source> + <translation>%ls: Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ Š² ŃŠµŠ»Š¾ŃŠøŃŠ»ŠµŠ½Š½Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1203"/> + <source>%ls: unable to convert to choice value +</source> + <translation>%ls: Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ Š² Š·Š½Š°ŃŠµŠ½ŠøŠµ Š²ŃŠ±Š¾ŃŠ° +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1213"/> + <source>%ls: values: %Rhra</source> + <translation>%ls: Š·Š½Š°ŃŠµŠ½ŠøŃ: %Rhra</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1223"/> + <source>%ls: selectedIndex: %Rhra</source> + <translation>%ls: Š²ŃŠ±ŃŠ°Š½Š½ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ: %Rhra</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1231"/> + <source>%ls: selected index %RI64 out of range [0, %zu) +</source> + <translation>%ls: Š²ŃŠ±ŃŠ°Š½Š½ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ %RI64 Š²Š½Šµ Š³ŃŠ°Š½ŠøŃ Š“ŠøŠ°ŠæŠ°Š·Š¾Š½Š° [0, %zu) +</translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1243"/> + <source>unknown value type %RU32 +</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½ŃŠ¹ ŃŠøŠæ Š·Š½Š°ŃŠµŠ½ŠøŃ %RU32 +</translation> + </message> +</context> +<context> + <name>CloudVM</name> + <message> + <source>Invalid %s number '%s'</source> + <translation type="vanished">ŠŠµŠ“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŃŠ½ŃŠ¹ Š½Š¾Š¼ŠµŃ %s '%s'</translation> + </message> + <message> + <source>Failed to send a scancode</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾ŃŠ»Š°ŃŃ ŃŠŗŠ°Š½ŠŗŠ¾Š“</translation> + </message> + <message numerus="yes"> + <source>Only %d scancodes were stored</source> + <translation type="vanished"> + <numerusform>Š”Š¾Ń
ŃŠ°Š½ŠµŠ½ ŃŠ¾Š»ŃŠŗŠ¾ %d ŃŠŗŠ°Š½ŠŗŠ¾Š“</numerusform> + <numerusform>Š”Š¾Ń
ŃŠ°Š½ŠµŠ½Š¾ ŃŠ¾Š»ŃŠŗŠ¾ %d ŃŠŗŠ°Š½ŠŗŠ¾Š“Š°</numerusform> + <numerusform>Š”Š¾Ń
ŃŠ°Š½ŠµŠ½Š¾ ŃŠ¾Š»ŃŠŗŠ¾ %d ŃŠŗŠ°Š½ŠŗŠ¾Š“Š¾Š²</numerusform> + </translation> + </message> + <message numerus="yes"> + <source>Out of memory allocating %d bytes</source> + <translation type="vanished"> + <numerusform>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ Š±ŃŃŠµŃ %d Š±Š°Š¹Ń</numerusform> + <numerusform>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ Š±ŃŃŠµŃ %d Š±Š°Š¹ŃŠ°</numerusform> + <numerusform>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ Š±ŃŃŠµŃ %d Š±Š°Š¹Ń</numerusform> + </translation> + </message> + <message> + <source>File size %RI64 is greater than %RI64: '%s'</source> + <translation type="vanished">Š Š°Š·Š¼ŠµŃ ŃŠ°Š¹Š»Š° %RI64 Š±Š¾Š»ŃŃŠµ ŃŠµŠ¼ %RI64: '%s'</translation> + </message> + <message> + <source>Cannot get size of file '%s': %Rrc</source> + <translation type="vanished">ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ ŃŠ°Š¹Š»Š° '%s': %Rrc</translation> + </message> + <message> + <source>Cannot open file '%s': %Rrc</source> + <translation type="vanished">ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ ŃŠ°Š¹Š» '%s': %Rrc</translation> + </message> + <message> + <source>Not enough parameters</source> + <translation type="vanished">ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <source>Machine '%s' is not currently running</source> + <translation type="vanished">ŠŠ°ŃŠøŠ½Š° '%s' ŃŠµŠ¹ŃŠ°Ń Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š°</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected CPU number.</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ Š½Š¾Š¼ŠµŃ Š¦ŠŠ£.</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected execution cap number.</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ %% Š²ŃŠµŠ¼ŠµŠ½Šø Š² %% Š²ŃŠ“ŠµŠ»ŠµŠ½Š½Š¾Š³Š¾ Š“Š»Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ.</translation> + </message> + <message> + <source>Invalid value '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ '%s'</translation> + </message> + <message> + <source>audio adapter not enabled in VM configuration</source> + <translation type="vanished">Š°ŃŠ“ŠøŠ¾ Š°Š“Š°ŠæŃŠµŃ Š½Šµ Š²ŠŗŠ»ŃŃŠµŠ½ Š² ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø ŠŠ</translation> + </message> + <message> + <source>Missing argument to '%s'.</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'.</translation> + </message> + <message> + <source>Invalid '%s' argument '%s'.</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s' '%s'.</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected enabled / disabled.</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ enabled / disabled.</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected drag and drop mode.</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŃŠµŠ¶ŠøŠ¼ drag and drop.</translation> + </message> + <message> + <source>Failed to power off machine</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠŗŠ»ŃŃŠøŃŃ Š¼Š°ŃŠøŠ½Ń</translation> + </message> + <message> + <source>Machine in invalid state %d -- %s +</source> + <translation type="vanished">ŠŠ°ŃŠøŠ½Š° Š² Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Š¼ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠø %d -- %s +</translation> + </message> + <message> + <source>Failed to save machine state</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Ń
ŃŠ°Š½ŠøŃŃ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ Š¼Š°ŃŠøŠ½Ń</translation> + </message> + <message> + <source>Guest not running</source> + <translation type="vanished">ŠŠ¾ŃŃŠµŠ²Š°Ń ŃŠøŃŃŠµŠ¼Š° Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š°</translation> + </message> + <message> + <source>Current installed Guest Additions don't support %s the guest.</source> + <translation type="vanished">Š¢ŠµŠŗŃŃŠøŠµ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š½ŃŠµ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŃŃ %s Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń.</translation> + </message> + <message> + <source>rebooting</source> + <translation type="vanished">ŠæŠµŃŠµŠ·Š°Š³ŃŃŠ·ŠŗŃ</translation> + </message> + <message> + <source>shutting down</source> + <translation type="vanished">Š·Š°Š²ŠµŃŃŠµŠ½ŠøŠµ</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŃŃŃŃ ŃŠŗŠ°Š½ŠŗŠ¾Š“Ń ŠŗŠ»Š°Š²ŠøŠ°ŃŃŃŃ IBM PC AT set 2 Š² Š²ŠøŠ“Šµ hex Š±Š°Š¹ŃŠ¾Š².</translation> + </message> + <message> + <source>Converting '%s' returned %Rrc!</source> + <translation type="vanished">ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ '%s' Š²ŠµŃŠ½ŃŠ»Š¾ %Rrc!</translation> + </message> + <message> + <source>Error: '%s' is not a hex byte!</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ°: '%s' Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ hex Š±Š°Š¹ŃŠ¾Š¼!</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected ASCII string(s).</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŃŃŃŠ¾ŠŗŠ° ASCII.</translation> + </message> + <message> + <source>Missing argument to '%s'. Expected file name.</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŠøŠ¼Ń ŃŠ°Š¹Š»Š°.</translation> + </message> + <message> + <source>Missing argument to '%s'</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <source>Invalid link state '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŃ '%s'</translation> + </message> + <message> + <source>Invalid filename or filename not specified for NIC %lu</source> + <translation type="vanished">ŠŠµŠ“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŃŠ½Š¾Šµ ŠøŠ¼Ń ŃŠ°Š¹Š»Š° ŠøŠ»Šø ŠøŠ¼Ń ŃŠ°Š¹Š»Š° Š½Šµ ŃŠŗŠ°Š·Š°Š½Š¾ Š“Š»Ń ŃŠµŃŠµŠ²Š¾Š³Š¾ Š°Š“Š°ŠæŃŠµŃŠ° %lu</translation> + </message> + <message> + <source>The NIC %d is currently disabled and thus its tracefile can't be changed</source> + <translation type="vanished">NIC %d Š² Š½Š°ŃŃŠ¾ŃŃŠµŠµ Š²ŃŠµŠ¼Ń Š¾ŃŠŗŠ»ŃŃŠµŠ½ Šø ŠæŠ¾ŃŃŠ¾Š¼Ń ŠµŠ³Š¾ ŃŃŠ°ŃŃŠøŃŠ¾Š²Š¾ŃŠ½ŃŠ¹ ŃŠ°Š¹Š» Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½</translation> + </message> + <message> + <source>Invalid nictrace%lu argument '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ nictrace%lu '%s'</translation> + </message> + <message> + <source>The NIC %d is currently disabled and thus its trace flag can't be changed</source> + <translation type="vanished">NIC %d Š² Š½Š°ŃŃŠ¾ŃŃŠµŠµ Š²ŃŠµŠ¼Ń Š¾ŃŠŗŠ»ŃŃŠµŠ½ Šø ŠæŠ¾ŃŃŠ¾Š¼Ń ŠµŠ³Š¾ ŃŃŠ°ŃŃŠøŃŠ¾Š²Š¾ŃŠ½ŃŠ¹ ŃŠ»Š°Š³ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½</translation> + </message> + <message> + <source>Missing or invalid argument to '%s'</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ»Šø Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <source>Wrong rule proto '%s' specified -- only 'udp' and 'tcp' are allowed.</source> + <translation type="vanished">Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠæŃŠ°Š²ŠøŠ»ŃŠ½ŃŠ¹ ŠæŃŠ¾ŃŠ¾ŠŗŠ¾Š» ŠæŃŠ°Š²ŠøŠ»Š° '%s' -- ŃŠ°Š·ŃŠµŃŠµŠ½Ń ŃŠ¾Š»ŃŠŗŠ¾ 'udp' Šø 'tcp'.</translation> + </message> + <message> + <source>Invalid nicproperty%d argument '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ nicproperty%d '%s'</translation> + </message> + <message> + <source>Error: Failed to allocate memory for nicproperty%d '%s' +</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ°: ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠ“ŠµŠ»ŠøŃŃ ŠæŠ°Š¼ŃŃŃ Š“Š»Ń nicproperty%d '%s' +</translation> + </message> + <message> + <source>The NIC %d is currently disabled and thus its properties can't be changed</source> + <translation type="vanished">NIC %d Š¾ŃŠŗŠ»ŃŃŠµŠ½ Š² Š½Š°ŃŃŠ¾ŃŃŠµŠµ Š²ŃŠµŠ¼Ń, Šø ŠæŠ¾ŃŃŠ¾Š¼Ń Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŠµŠ³Š¾ ŃŠ²Š¾Š¹ŃŃŠ²Š°</translation> + </message> + <message> + <source>Unknown promiscuous mode policy '%s'</source> + <translation type="vanished">ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŠæŠ¾Š»ŠøŃŠøŠŗŠ° Š½ŠµŃŠ°Š·Š±Š¾ŃŃŠøŠ²Š¾Š³Š¾ ŃŠµŠ¶ŠøŠ¼Š° '%s'</translation> + </message> + <message> + <source>The NIC %d is currently disabled and thus its promiscuous mode can't be changed</source> + <translation type="vanished">NIC %d Š¾ŃŠŗŠ»ŃŃŠµŠ½ Š² Š½Š°ŃŃŠ¾ŃŃŠµŠµ Š²ŃŠµŠ¼Ń, Šø ŠæŠ¾ŃŃŠ¾Š¼Ń Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠøŠ·Š¼ŠµŠ½ŠøŃŃ Š½ŠµŃŠ°Š·Š±Š¾ŃŃŠøŠ²ŃŠ¹ ŃŠµŠ¶ŠøŠ¼</translation> + </message> + <message> + <source>Invalid type '%s' specfied for NIC %lu</source> + <translation type="vanished">Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ '%s' Š“Š»Ń NIC %lu</translation> + </message> + <message> + <source>The NIC %d is currently disabled and thus its attachment type can't be changed</source> + <translation type="vanished">NIC %d Š¾ŃŠŗŠ»ŃŃŠµŠ½ Š² Š½Š°ŃŃŠ¾ŃŃŠµŠµ Š²ŃŠµŠ¼Ń, Šø ŠæŠ¾ŃŃŠ¾Š¼Ń Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠøŠæ ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŃ</translation> + </message> + <message> + <source>Warning: 'vrdp' is deprecated. Use 'vrde'. +</source> + <translation type="vanished">ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: 'vrdp' ŃŃŃŠ°ŃŠµŠ». ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ 'vrde'. +</translation> + </message> + <message> + <source>Invalid remote desktop server state '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ ŃŠµŃŠ²ŠµŃŠ° ŃŠ“Š°Š»ŠµŠ½Š½Š¾Š³Š¾ ŃŠ°Š±Š¾ŃŠµŠ³Š¾ ŃŃŠ¾Š»Š° '%s'</translation> + </message> + <message> + <source>Warning: 'vrdpport' is deprecated. Use 'vrdeport'. +</source> + <translation type="vanished">ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: 'vrdpport' ŃŃŃŠ°ŃŠµŠ». ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ 'vrdeport'. +</translation> + </message> + <message> + <source>Warning: 'vrdpvideochannelquality' is deprecated. Use 'vrdevideochannelquality'. +</source> + <translation type="vanished">ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: 'vrdpvideochannelquality' ŃŃŃŠ°ŃŠµŠ». ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ 'vrdevideochannelquality'. +</translation> + </message> + <message> + <source>Invalid vrdeproperty argument '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ vrdeproperty '%s'</translation> + </message> + <message> + <source>Error: Failed to allocate memory for VRDE property '%s' +</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ°: ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠ“ŠµŠ»ŠøŃŃ ŠæŠ°Š¼ŃŃŃ Š“Š»Ń ŃŠ²Š¾Š¹ŃŃŠ²Š° VRDE '%s' +</translation> + </message> + <message> + <source>Wrong number of arguments</source> + <translation type="vanished">ŠŠµŠæŃŠ°Š²ŠøŠ»ŃŠ½Š¾Šµ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ¾Š²</translation> + </message> + <message> + <source>Invalid parameter '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <source>Zero UUID argument '%s'</source> + <translation type="vanished">ŠŃŠ»ŠµŠ²Š¾Š¹ UUID Š°ŃŠ³ŃŠ¼ŠµŠ½Ń '%s'</translation> + </message> + <message> + <source>Incorrect number of parameters</source> + <translation type="vanished">ŠŠµŠŗŠ¾ŃŃŠµŠŗŃŠ½Š¾Šµ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <source>Either "yes" or "no" is expected</source> + <translation type="vanished">ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŃŠ¾Š»ŃŠŗŠ¾ "yes" ŠøŠ»Šø "no"</translation> + </message> + <message> + <source>Display status must be <on> or <off></source> + <translation type="vanished">Š”ŃŠ°ŃŃŃ ŃŠŗŃŠ°Š½Š° Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ <on> ŠøŠ»Šø <off></translation> + </message> + <message> + <source>Invalid host DVD drive name "%s"</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń DVD Š“ŠøŃŠŗŠ¾Š²Š¾Š“Š° Ń
Š¾ŃŃŠ° "%s"</translation> + </message> + <message> + <source>IDE Controller</source> + <translation type="vanished">IDE ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ</translation> + </message> + <message> + <source>Invalid host floppy drive name "%s"</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń ŃŠ»Š¾ŠæŠæŠø Š“ŠøŃŠŗŠ¾Š²Š¾Š“Š° Ń
Š¾ŃŃŠ° "%s"</translation> + </message> + <message> + <source>Floppy Controller</source> + <translation type="vanished">Š¤Š»Š¾ŠæŠæŠø ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ</translation> + </message> + <message> + <source>Error parsing guest memory balloon size '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŃŠ°Š·Š±Š¾ŃŠ° ŃŠ°Š·Š¼ŠµŃŠ° balloon ŠæŠ°Š¼ŃŃŠø Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń '%s'</translation> + </message> + <message> + <source>Teleportation failed</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŠøŠ·Š²ŠµŃŃŠø ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½ŠøŠµ</translation> + </message> + <message> + <source>Error parsing display number '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŃŠ°Š·Š±Š¾ŃŠ° Š½Š¾Š¼ŠµŃŠ° ŃŠŗŃŠ°Š½Š° '%s'</translation> + </message> + <message> + <source>Failed to create file '%s' (%Rrc)</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ ŃŠ°Š¹Š» '%s' (%Rrc)</translation> + </message> + <message> + <source>Failed to write screenshot to file '%s' (%Rrc)</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŠøŃŠ°ŃŃ ŃŠ½ŠøŠ¼Š¾Šŗ ŃŠŗŃŠ°Š½Š° Š² ŃŠ°Š¹Š» '%s' (%Rrc)</translation> + </message> + <message> + <source>Invalid screen ID specified '%u'</source> + <translation type="vanished">Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ID ŃŠŗŃŠ°Š½Š° '%u'</translation> + </message> + <message> + <source>Error parsing video width '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ ŃŠøŃŠøŠ½Ń Š²ŠøŠ“ŠµŠ¾ '%s'</translation> + </message> + <message> + <source>Error parsing video height '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š²ŃŃŠ¾ŃŃ Š²ŠøŠ“ŠµŠ¾ '%s'</translation> + </message> + <message> + <source>Error parsing video rate '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š±ŠøŃŃŠµŠ¹ŃŠ° Š²ŠøŠ“ŠµŠ¾ '%s'</translation> + </message> + <message> + <source>Error parsing video FPS '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ FPS Š²ŠøŠ“ŠµŠ¾ '%s'</translation> + </message> + <message> + <source>Error parsing maximum time '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾Š³Š¾ Š²ŃŠµŠ¼ŠµŠ½Šø '%s'</translation> + </message> + <message> + <source>Error parsing maximum file size '%s'</source> + <translation type="vanished">ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾Š³Š¾ ŃŠ°Š·Š¼ŠµŃŠ° ŃŠ°Š¹Š»Š° '%s'</translation> + </message> + <message> + <source>Invalid argument to '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <source>Invalid parameters</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ</translation> + </message> + <message> + <source>Enter password:</source> + <translation type="vanished">ŠŠ²ŠµŠ“ŠøŃŠµ ŠæŠ°ŃŠ¾Š»Ń:</translation> + </message> + <message> + <source>Failed to read new password from file</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ Š½Š¾Š²ŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń ŠøŠ· ŃŠ°Š¹Š»Š°</translation> + </message> + <message> + <source>Incorrect arguments to '%s'</source> + <translation type="vanished">ŠŠµŠŗŠ¾ŃŃŠµŠŗŃŠ½ŃŠµ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŃ Šŗ '%s'</translation> + </message> + <message> + <source>Invalid vm-process-priority '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ vm-process-priority '%s'</translation> + </message> + <message> + <source>Invalid autostart delay number '%s'</source> + <translation type="vanished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š²ŃŠµŠ¼Ń Š·Š°Š“ŠµŃŠ¶ŠŗŠø Š°Š²ŃŠ¾ŃŃŠ°ŃŃŠ° '%s'</translation> + </message> +</context> +<context> + <name>ControlVM</name> + <message> + <location filename="../VBoxManageControlVM.cpp" line="65"/> + <source>Invalid %s number '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="222"/> + <source>Failed to send a scancode.</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageControlVM.cpp" line="323"/> + <source>Out of memory allocating %d bytes.</source> + <translation type="unfinished"> + <numerusform></numerusform> + <numerusform></numerusform> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="326"/> + <source>File size %RI64 is greater than %RI64: '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="329"/> + <source>Cannot get size of file '%s': %Rrc.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="334"/> + <source>Cannot open file '%s': %Rrc.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="351"/> + <location filename="../VBoxManageControlVM.cpp" line="1372"/> + <source>Not enough parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="371"/> + <source>Machine '%s' is not currently running.</source> + <translation type="unfinished">ŠŠ°ŃŠøŠ½Š° '%s' ŃŠµŠ¹ŃŠ°Ń Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š°.</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="397"/> + <location filename="../VBoxManageControlVM.cpp" line="411"/> + <location filename="../VBoxManageControlVM.cpp" line="425"/> + <location filename="../VBoxManageControlVM.cpp" line="487"/> + <location filename="../VBoxManageControlVM.cpp" line="558"/> + <location filename="../VBoxManageControlVM.cpp" line="782"/> + <location filename="../VBoxManageControlVM.cpp" line="802"/> + <location filename="../VBoxManageControlVM.cpp" line="840"/> + <location filename="../VBoxManageControlVM.cpp" line="884"/> + <location filename="../VBoxManageControlVM.cpp" line="925"/> + <location filename="../VBoxManageControlVM.cpp" line="1019"/> + <location filename="../VBoxManageControlVM.cpp" line="1081"/> + <location filename="../VBoxManageControlVM.cpp" line="1131"/> + <location filename="../VBoxManageControlVM.cpp" line="1160"/> + <location filename="../VBoxManageControlVM.cpp" line="1172"/> + <location filename="../VBoxManageControlVM.cpp" line="1184"/> + <location filename="../VBoxManageControlVM.cpp" line="1197"/> + <location filename="../VBoxManageControlVM.cpp" line="1208"/> + <location filename="../VBoxManageControlVM.cpp" line="1237"/> + <location filename="../VBoxManageControlVM.cpp" line="1266"/> + <location filename="../VBoxManageControlVM.cpp" line="1297"/> + <location filename="../VBoxManageControlVM.cpp" line="1318"/> + <location filename="../VBoxManageControlVM.cpp" line="1992"/> + <location filename="../VBoxManageControlVM.cpp" line="2115"/> + <source>Missing argument to '%s'.</source> + <translation type="unfinished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'.</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="444"/> + <location filename="../VBoxManageControlVM.cpp" line="468"/> + <location filename="../VBoxManageControlVM.cpp" line="2226"/> + <source>Invalid value '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="453"/> + <location filename="../VBoxManageControlVM.cpp" line="477"/> + <source>Audio adapter not enabled in VM configuration.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="498"/> + <location filename="../VBoxManageControlVM.cpp" line="528"/> + <source>Missing argument to '%s %s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="513"/> + <location filename="../VBoxManageControlVM.cpp" line="536"/> + <source>Invalid '%s %s' argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="547"/> + <location filename="../VBoxManageControlVM.cpp" line="574"/> + <source>Invalid '%s' argument '%s'.</source> + <translation type="unfinished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s' '%s'.</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="591"/> + <source>Failed to power off machine.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="611"/> + <source>Machine in invalid state %d -- %s.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="634"/> + <source>Failed to save machine state.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="665"/> + <location filename="../VBoxManageControlVM.cpp" line="700"/> + <location filename="../VBoxManageControlVM.cpp" line="754"/> + <location filename="../VBoxManageControlVM.cpp" line="775"/> + <location filename="../VBoxManageControlVM.cpp" line="1478"/> + <location filename="../VBoxManageControlVM.cpp" line="1500"/> + <location filename="../VBoxManageControlVM.cpp" line="1624"/> + <location filename="../VBoxManageControlVM.cpp" line="1658"/> + <location filename="../VBoxManageControlVM.cpp" line="1755"/> + <location filename="../VBoxManageControlVM.cpp" line="2001"/> + <source>Guest not running.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="686"/> + <source>Current installed Guest Additions don't support rebooting the guest.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="688"/> + <source>Current installed Guest Additions don't support shutting down the guest.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="707"/> + <source>Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="727"/> + <source>Converting '%s' returned %Rrc!</source> + <translation type="unfinished">ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ '%s' Š²ŠµŃŠ½ŃŠ»Š¾ %Rrc!</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="736"/> + <source>'%s' is not a hex byte!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="761"/> + <source>Missing argument to '%s'. Expected ASCII string(s).</source> + <translation type="unfinished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'. ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŃŃŃŠ¾ŠŗŠ° ASCII.</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="814"/> + <source>Invalid link state '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="860"/> + <source>Filename not specified for NIC %lu.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="868"/> + <source>The NIC %d is currently disabled and thus its tracefile can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="901"/> + <source>Invalid nictrace%lu argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="909"/> + <source>The NIC %d is currently disabled and thus its trace flag can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="961"/> + <source>Missing or invalid argument to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="996"/> + <source>Wrong rule proto '%s' specified -- only 'udp' and 'tcp' are allowed.</source> + <translation type="unfinished">Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠæŃŠ°Š²ŠøŠ»ŃŠ½ŃŠ¹ ŠæŃŠ¾ŃŠ¾ŠŗŠ¾Š» ŠæŃŠ°Š²ŠøŠ»Š° '%s' -- ŃŠ°Š·ŃŠµŃŠµŠ½Ń ŃŠ¾Š»ŃŠŗŠ¾ 'udp' Šø 'tcp'.</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1050"/> + <source>Invalid nicproperty%d argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1057"/> + <source>Failed to allocate memory for nicproperty%d '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1065"/> + <source>The NIC %d is currently disabled and thus its properties can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1105"/> + <source>Unknown promiscuous mode policy '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1115"/> + <source>The NIC %d is currently disabled and thus its promiscuous mode can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1217"/> + <source>Invalid type '%s' specfied for NIC %lu.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1225"/> + <source>The NIC %d is currently disabled and thus its attachment type can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1233"/> + <source>'vrdp' is deprecated. Use 'vrde'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1249"/> + <source>Invalid remote desktop server state '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1262"/> + <source>'vrdpport' is deprecated. Use 'vrdeport'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1293"/> + <source>'vrdpvideochannelquality' is deprecated. Use 'vrdevideochannelquality'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1344"/> + <source>Invalid vrdeproperty argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1351"/> + <source>Failed to allocate memory for VRDE property '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1378"/> + <source>Wrong number of arguments.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1392"/> + <location filename="../VBoxManageControlVM.cpp" line="1587"/> + <location filename="../VBoxManageControlVM.cpp" line="2259"/> + <source>Invalid parameter '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1425"/> + <source>Zero UUID argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1444"/> + <location filename="../VBoxManageControlVM.cpp" line="1491"/> + <location filename="../VBoxManageControlVM.cpp" line="1542"/> + <location filename="../VBoxManageControlVM.cpp" line="1599"/> + <location filename="../VBoxManageControlVM.cpp" line="1638"/> + <location filename="../VBoxManageControlVM.cpp" line="1735"/> + <location filename="../VBoxManageControlVM.cpp" line="1787"/> + <location filename="../VBoxManageControlVM.cpp" line="1821"/> + <location filename="../VBoxManageControlVM.cpp" line="1840"/> + <location filename="../VBoxManageControlVM.cpp" line="1854"/> + <location filename="../VBoxManageControlVM.cpp" line="1888"/> + <location filename="../VBoxManageControlVM.cpp" line="1910"/> + <location filename="../VBoxManageControlVM.cpp" line="1932"/> + <location filename="../VBoxManageControlVM.cpp" line="1954"/> + <location filename="../VBoxManageControlVM.cpp" line="1978"/> + <location filename="../VBoxManageControlVM.cpp" line="2048"/> + <location filename="../VBoxManageControlVM.cpp" line="2093"/> + <source>Incorrect number of parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1462"/> + <source>Either "yes" or "no" is expected.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1527"/> + <source>Display status must be <on> or <off>.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1647"/> + <source>Error parsing guest memory balloon size '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1728"/> + <source>Teleportation failed</source> + <translation type="unfinished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŠøŠ·Š²ŠµŃŃŠø ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1746"/> + <source>Error parsing display number '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1769"/> + <source>Failed to create file '%s' (%Rrc).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1776"/> + <source>Failed to write screenshot to file '%s' (%Rrc).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1827"/> + <source>Error parsing list of screen IDs '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1863"/> + <source>Error parsing video width '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1872"/> + <source>Error parsing video height '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1897"/> + <source>Error parsing video rate '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1919"/> + <source>Error parsing video FPS '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1941"/> + <source>Error parsing maximum time '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1963"/> + <source>Error parsing maximum file size '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2037"/> + <source>Invalid argument to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2059"/> + <source>Invalid parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2072"/> + <source>Enter password:</source> + <translation type="unfinished">ŠŠ²ŠµŠ“ŠøŃŠµ ŠæŠ°ŃŠ¾Š»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2081"/> + <source>Failed to read new password from file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2129"/> + <location filename="../VBoxManageControlVM.cpp" line="2144"/> + <location filename="../VBoxManageControlVM.cpp" line="2185"/> + <location filename="../VBoxManageControlVM.cpp" line="2198"/> + <location filename="../VBoxManageControlVM.cpp" line="2219"/> + <location filename="../VBoxManageControlVM.cpp" line="2239"/> + <source>Incorrect arguments to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2205"/> + <source>Invalid vm-process-priority '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2248"/> + <source>Invalid autostart delay number '%s'.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>DHCPServer</name> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="65"/> + <source>Either --network or --interface, not both</source> + <translation>ŠŠ»Šø --network ŠøŠ»Šø --interface, Š½Šµ Š²Š¼ŠµŃŃŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="70"/> + <source>Either --interface or --network, not both</source> + <translation>ŠŠ»Šø --interface ŠøŠ»Šø --network, Š½Šµ Š²Š¼ŠµŃŃŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="180"/> + <source>Failed to locate host-only interface '%s'</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾Š±Š½Š°ŃŃŠ¶ŠøŃŃ Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠ¹ ŠøŠ½ŃŠµŃŃŠµŠ¹Ń Ń
Š¾ŃŃŠ°'%s'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="194"/> + <source>Failed to find DHCP server for network '%s'</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š½Š°Š¹ŃŠø DHCP ŃŠµŃŠ²ŠµŃ Š“Š»Ń ŃŠµŃŠø '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="196"/> + <source>Failed to find DHCP server for host-only interface '%s' (network '%ls')</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š½Š°Š¹ŃŠø DHCP ŃŠµŃŠ²ŠµŃ Š“Š»Ń Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ ŠøŠ½ŃŠµŃŃŠµŠ¹ŃŠ° Ń
Š¾ŃŃŠ° '%s' (ŃŠµŃŃ '%ls')</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="200"/> + <location filename="../VBoxManageDHCPServer.cpp" line="890"/> + <source>You need to specify either --network or --interface to identify the DHCP server</source> + <translation>ŠŃŠ¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ Š»ŠøŠ±Š¾ --network Š»ŠøŠ±Š¾ --interface Š“Š»Ń ŠøŠ“ŠµŠ½ŃŠøŃŠøŠŗŠ°ŃŠøŠø DHCP ŃŠµŃŠ²ŠµŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="474"/> + <source>Incomplete option sequence preseeding '--global'</source> + <translation>ŠŠµŠæŠ¾Š»Š½Š°Ń ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½Š¾ŃŃŃ Š¾ŠæŃŠøŠ¹ ŠæŠµŃŠµŠ“ '--global'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="480"/> + <source>Incomplete option sequence preseeding '--group'</source> + <translation>ŠŠµŠæŠ¾Š»Š½Š°Ń ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½Š¾ŃŃŃ Š¾ŠæŃŠøŠ¹ ŠæŠµŃŠµŠ“ '--group'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="482"/> + <source>Group name cannot be empty</source> + <translation>ŠŠ¼Ń Š³ŃŃŠæŠæŃ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠæŃŃŃŃŠ¼</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="488"/> + <source>Incomplete option sequence preseeding '--mac-address'</source> + <translation>ŠŠµŠæŠ¾Š»Š½Š°Ń ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½Š¾ŃŃŃ Š¾ŠæŃŠøŠ¹ ŠæŠµŃŠµŠ“ '--mac-address'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="495"/> + <source>Incomplete option sequence preseeding '--vm'</source> + <translation>ŠŠµŠæŠ¾Š»Š½Š°Ń ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½Š¾ŃŃŃ Š¾ŠæŃŠøŠ¹ ŠæŠµŃŠµŠ“ '--vm'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="501"/> + <source>--nic option requires a --vm preceeding selecting the VM it should apply to</source> + <translation>ŠŠæŃŠøŃ --nic ŃŃŠµŠ±ŃŠµŃ Š½Š°Š»ŠøŃŠøŃ ŠæŃŠµŠ“ŃŠµŃŃŠ²ŃŃŃŠµŠ¹ --vm Š“Š»Ń Š²ŃŠ±Š¾ŃŠ° ŠŠ, Šŗ ŠŗŠ¾ŃŠ¾ŃŠ¾Š¹ Š“Š°Š½Š½Š°Ń Š¾ŠæŃŠøŃ ŠæŃŠøŠ¼ŠµŠ½ŃŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="503"/> + <source>Incomplete option sequence preseeding '--nic=%u</source> + <translation>ŠŠµŠæŠ¾Š»Š½Š°Ń ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½Š¾ŃŃŃ Š¾ŠæŃŠøŠ¹ ŠæŠµŃŠµŠ“ '--nic=%u'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="505"/> + <source>invalid NIC number: %u</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š½Š¾Š¼ŠµŃ NIC: %u</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="540"/> + <source>Malformed hex string given to --set-opt-hex %u: %s +</source> + <translation>ŠŠµŠæŃŠ°Š²ŠøŠ»ŃŠ½Š°Ń hex ŃŃŃŠ¾ŠŗŠ° ŃŠŗŠ°Š·Š°Š½Š½Š°Ń Š² --set-opt-hex %u: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="555"/> + <source>--del-opt does not apply to the 'add' subcommand</source> + <translation>--del-opt Š½Šµ ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š° Šŗ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Šµ 'add'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="567"/> + <source>--unforce-opt does not apply to the 'add' subcommand</source> + <translation>--unforce-opt Š½Šµ ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š° Šŗ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Šµ 'add'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="571"/> + <source>--unsuppress-opt does not apply to the 'add' subcommand</source> + <translation>--unsuppress-opt Š½Šµ ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š° Šŗ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Šµ 'add'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="629"/> + <source>--zap-options does not apply to the 'add' subcommand</source> + <translation>--zap-options Š½Šµ ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š° Šŗ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Šµ 'add'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="671"/> + <source>--remove-config does not apply to the 'add' subcommand</source> + <translation>--remove-config Š½Šµ ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š° Šŗ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Šµ 'add'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="673"/> + <source>--remove-config cannot be applied to the global config</source> + <translation>--remove-config Š½Šµ Š¼Š¾Š¶ŠµŃ ŠæŃŠøŠ¼ŠµŠ½ŃŃŃŃŃ Šŗ Š³Š»Š¾Š±Š°Š»ŃŠ½Š¾Š¹ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="686"/> + <source>--fixed-address can only be applied to a VM NIC or an MAC address</source> + <translation>--fixed-address ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š¾ ŃŠ¾Š»ŃŠŗŠ¾ Šŗ NIC ŠŠ ŠøŠ»Šø MAC Š°Š“ŃŠµŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="720"/> + <source>A group must be selected to perform condition alterations.</source> + <translation>ŠŠ»Ń ŠæŃŠ¾Š²ŠµŠ“ŠµŠ½ŠøŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŠ¹ ŠæŠ¾ ŃŃŠ»Š¾Š²ŠøŃ Š“Š¾Š»Š¶Š½Š° Š±ŃŃŃ Š²ŃŠ±ŃŠ°Š½Š° Š³ŃŃŠæŠæŠ°.</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="722"/> + <source>Condition value cannot be empty</source> + <translation>ŠŠ½Š°ŃŠµŠ½ŠøŠµ ŃŃŠ»Š¾Š²ŠøŃ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠæŃŃŃŃŠ¼</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="815"/> + <source>Could not find any condition of type %d with value '%s' to delete</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠŗŠ°ŠŗŠ¾Šµ-Š»ŠøŠ±Š¾ ŃŃŠ»Š¾Š²ŠøŠµ ŃŠøŠæŠ° %d ŃŠ¾ Š·Š½Š°ŃŠµŠ½ŠøŠµŠ¼ '%s' Š“Š»Ń ŃŠ“Š°Š»ŠµŠ½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="823"/> + <source>--zap-conditions can only be with a group selected</source> + <translation>--zap-conditions Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Ń Š²ŃŠ±ŃŠ°Š½Š½Š¾Š¹ Š³ŃŃŠæŠæŠ¾Š¹</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="842"/> + <source>Incomplete option sequence preseeding '--id=%u</source> + <translation>ŠŠµŠæŠ¾Š»Š½Š°Ń ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½Š¾ŃŃŃ Š¾ŠæŃŠøŠ¹ ŠæŠµŃŠµŠ“ '--id=%u'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="849"/> + <source>--value without --id=dhcp-opt-no</source> + <translation>--value Š±ŠµŠ· --id=dhcp-opt-no</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="863"/> + <source>--remove does not apply to the 'add' subcommand</source> + <translation>--remove Š½Šµ ŠæŃŠøŠ¼ŠµŠ½ŠøŠ¼Š° Šŗ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Šµ 'add'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="865"/> + <source>--remove without --id=dhcp-opt-no</source> + <translation>--remove Š±ŠµŠ· --id=dhcp-opt-no</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="895"/> + <source>Missing required option: --ip</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŃŃŠµŠ±ŃŠµŠ¼Š°Ń Š¾ŠæŃŠøŃ: --ip</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="897"/> + <source>Missing required option: --netmask</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŃŃŠµŠ±ŃŠµŠ¼Š°Ń Š¾ŠæŃŠøŃ: --netmask</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="899"/> + <source>Missing required option: --lowerip</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŃŃŠµŠ±ŃŠµŠ¼Š°Ń Š¾ŠæŃŠøŃ: --lowerip</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="901"/> + <source>Missing required option: --upperip</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŃŃŠµŠ±ŃŠµŠ¼Š°Ń Š¾ŠæŃŠøŃ: --upperip</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="919"/> + <source>Could not find interface '%s'</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠøŠ½ŃŠµŃŃŠµŠ¹Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="923"/> + <source>Could not get network name for the interface '%s'</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ¼Ń ŃŠµŃŠø Š“Š»Ń ŠøŠ½ŃŠµŃŃŠµŠ¹ŃŠ° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="934"/> + <source>DHCP server already exists</source> + <translation>DHCP ŃŠµŃŠ²ŠµŃ ŃŠ¶Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="938"/> + <source>Failed to create the DHCP server</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ DHCP ŃŠµŃŠ²ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="941"/> + <source>DHCP server does not exist</source> + <translation>DHCP ŃŠµŃŠ²ŠµŃ Š½Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="973"/> + <source>Failed to set configuration (%ls, %ls, %ls, %ls)</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ (%ls, %ls, %ls, %ls)</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1025"/> + <source>Failed to remove server</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ ŃŠµŃŠ²ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1092"/> + <source>Failed to start the server</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŃŃŃŠøŃŃ ŃŠµŃŠ²ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1136"/> + <source>Failed to restart the server</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠµŃŠµŠ·Š°ŠæŃŃŃŠøŃŃ ŃŠµŃŠ²ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1180"/> + <source>Failed to stop the server</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŃŠ°Š½Š¾Š²ŠøŃŃ ŃŠµŃŠ²ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1227"/> + <source>You need to specify a MAC address too look for</source> + <translation>ŠŠµŠ¾Š±Ń
Š¾Š“ŠøŠ¼Š¾ ŃŠŗŠ°Š·Š°ŃŃ MAC Š°Š“ŃŠµŃ Š“Š»Ń ŠæŠ¾ŠøŃŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1255"/> + <source>IP Address: %ls +MAC Address: %RTmac +State: %ls +Issued: %s (%RU64) +Expire: %s (%RU64) +TTL: %RU64 sec, currently %RU64 sec left +</source> + <translation>IP Š°Š“ŃŠµŃ: %ls +MAC Š°Š“ŃŠµŃ: %RTmac +Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: %ls +ŠŃŠ“Š°Š½: %s (%RU64) +ŠŃŃŠµŠŗŠ°ŠµŃ: %s (%RU64) +TTL: %RU64 ŃŠµŠŗ, ŃŠµŠ¹ŃŠ°Ń %RU64 ŃŠµŠŗ Š¾ŃŃŠ°Š»Š¾ŃŃ +</translation> + </message> +</context> +<context> + <name>DebugVM</name> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="115"/> + <source>The getregisters sub-command takes at least one register name</source> + <translation>ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š° getregisters ŠæŃŠøŠ½ŠøŠ¼Š°ŠµŃ ŠøŠ¼Ń ŠŗŠ°Šŗ Š¼ŠøŠ½ŠøŠ¼ŃŠ¼ Š¾Š“Š½Š¾Š³Š¾ ŃŠµŠ³ŠøŃŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="156"/> + <source>Must specify info item to display</source> + <translation>ŠŠµŠ¾Š±Ń
Š¾Š“ŠøŠ¼Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ»ŠµŠ¼ŠµŠ½Ń Š“Š»Ń Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="303"/> + <source>The --compression option has already been given</source> + <translation>ŠŠæŃŠøŃ --compression ŃŠ¶Šµ ŠæŃŠµŠ“Š¾ŃŃŠ°Š²Š»ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="308"/> + <source>The --filename option has already been given</source> + <translation>ŠŠæŃŠøŃ --filename ŃŠ¶Šµ ŠæŃŠµŠ“Š¾ŃŃŠ°Š²Š»ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="317"/> + <source>The --filename option is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ Š¾ŠæŃŠøŃ --filename</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="325"/> + <source>RTPathAbs failed on '%s': %Rrc</source> + <translation>RTPathAbs Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="351"/> + <source>Detected: %ls +</source> + <translation>ŠŠ±Š½Š°ŃŃŠ¶ŠµŠ½Š¾: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="371"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="372"/> + <source>Version: %ls +</source> + <translation>ŠŠµŃŃŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="450"/> + <source>setregisters expects input on the form 'register=value' got '%s'</source> + <translation>setregisters Š¾Š¶ŠøŠ“Š°ŠµŃ Š²Ń
Š¾Š“Š½ŃŃ
Š“Š°Š½Š½ŃŃ
Š² ŃŠ¾ŃŠ¼Š°ŃŠµ 'ŃŠµŠ³ŠøŃŃŃ=Š·Š½Š°ŃŠµŠ½ŠøŠµ', ŠæŠ¾Š»ŃŃŠµŠ½Š¾ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="462"/> + <source>Out of memory +</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="474"/> + <source>The setregisters sub-command takes at least one register name</source> + <translation>ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š° setregisters ŠæŃŠøŠ½ŠøŠ¼Š°ŠµŃ ŠøŠ¼Ń ŠŗŠ°Šŗ Š¼ŠøŠ½ŠøŠ¼ŃŠ¼ Š¾Š“Š½Š¾Š³Š¾ ŃŠµŠ³ŠøŃŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="483"/> + <source>Successfully set %ls +</source> + <translation>Š£ŃŠæŠµŃŠ½Š¾ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½ %ls +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDebugVM.cpp" line="489"/> + <source>Successfully set %u registers +</source> + <translation> + <numerusform>Š£ŃŠæŠµŃŠ½Š¾ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š¾ %u ŃŠµŠ³ŠøŃŃŃ +</numerusform> + <numerusform>Š£ŃŠæŠµŃŠ½Š¾ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š¾ %u ŃŠµŠ³ŠøŃŃŃŠ° +</numerusform> + <numerusform>Š£ŃŠæŠµŃŠ½Š¾ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š¾ %u ŃŠµŠ³ŠøŃŃŃŠ¾Š² +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="516"/> + <source>export %s='%ls' +</source> + <translation>export %s='%ls' +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="518"/> + <source>set %s=%ls +</source> + <translation>set %s=%ls +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="533"/> + <source>Debug logger settings: +</source> + <translation>ŠŠ°ŃŃŃŠ¾Š¹ŠŗŠø Š¶ŃŃŠ½Š°Š»ŠøŃŠ¾Š²Š°Š½ŠøŃ (Š¾ŃŠ»Š°Š“ŠŗŠ°): +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="557"/> + <source>Release logger settings: +</source> + <translation>ŠŠ°ŃŃŃŠ¾Š¹ŠŗŠø Š¶ŃŃŠ½Š°Š»ŠøŃŠ¾Š²Š°Š½ŠøŃ (ŃŠµŠ»ŠøŠ·): +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="631"/> + <source>The show sub-command has no idea what '%s' might be</source> + <translation>Š£ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Ń show Š½ŠµŃ ŠøŠ“ŠµŠ¹ ŃŃŠ¾ ŃŃŠ¾ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ - '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="705"/> + <source>====================== CPU #%u ====================== +</source> + <translation>====================== Š¦ŠŠ£ #%u ====================== +</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="752"/> + <source>Multiple --pattern options are not permitted</source> + <translation>ŠŠ½Š¾Š¶ŠµŃŃŠ²ŠµŠ½Š½ŃŠµ Š¾ŠæŃŠøŠø --pattern Š½Šµ ŃŠ°Š·ŃŠµŃŠ°ŃŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="766"/> + <source>The --reset and --descriptions options does not mix</source> + <translation>ŠŠæŃŠøŠø --reset Šø --descriptions Š½Šµ ŃŠ¼ŠµŃŠøŠ²Š°ŃŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="836"/> + <source>The --filename is missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ --filename</translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="960"/> + <source>Machine '%s' is not currently running. +</source> + <translation>ŠŠ°ŃŠøŠ½Š° '%s' ŃŠµŠ¹ŃŠ°Ń Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š°. +</translation> + </message> +</context> +<context> + <name>Disk</name> + <message> + <location filename="../VBoxManageDisk.cpp" line="64"/> + <source>Error code %Rrc at %s(%u) in function %s</source> + <translation>ŠŠ¾Š“ Š¾ŃŠøŠ±ŠŗŠø %Rrc Š² %s(%u) Š² ŃŃŠ½ŠŗŃŠøŠø %s</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="184"/> + <location filename="../VBoxManageDisk.cpp" line="219"/> + <source>Cannot convert filename "%s" to absolute path</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ ŠøŠ¼Ń ŃŠ°Š¹Š»Š° "%s" Š² Š°Š±ŃŠ¾Š»ŃŃŠ½ŃŠ¹ ŠæŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="288"/> + <source>Out of memory copying '%s'</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø Š“Š»Ń ŠŗŠ¾ŠæŠøŃŠ¾Š²Š°Š½ŠøŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="328"/> + <location filename="../VBoxManageDisk.cpp" line="334"/> + <location filename="../VBoxManageDisk.cpp" line="340"/> + <location filename="../VBoxManageDisk.cpp" line="699"/> + <location filename="../VBoxManageDisk.cpp" line="705"/> + <location filename="../VBoxManageDisk.cpp" line="711"/> + <location filename="../VBoxManageDisk.cpp" line="1025"/> + <location filename="../VBoxManageDisk.cpp" line="1031"/> + <location filename="../VBoxManageDisk.cpp" line="1037"/> + <location filename="../VBoxManageDisk.cpp" line="1660"/> + <location filename="../VBoxManageDisk.cpp" line="1666"/> + <location filename="../VBoxManageDisk.cpp" line="1672"/> + <location filename="../VBoxManageDisk.cpp" line="1772"/> + <location filename="../VBoxManageDisk.cpp" line="1778"/> + <location filename="../VBoxManageDisk.cpp" line="1784"/> + <source>Only one command can be specified: '%s'</source> + <translation>ŠŠ¾Š¶ŠµŃ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½Š° ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“Š½Š° ŠŗŠ¾Š¼Š°Š½Š“Š°: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="371"/> + <source>Invalid key value pair: No '='.</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠæŠ°ŃŠ° ŠŗŠ»ŃŃ/Š·Š½Š°ŃŠµŠ½ŠøŠµ: ŠŠµŃ '='.</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="387"/> + <source>Cannot open replacement value file '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ ŃŠ°Š¹Š» Ń ŠæŠ¾Š“Š¼ŠµŠ½ŃŠµŠ¼ŃŠ¼ Š·Š½Š°ŃŠµŠ½ŠøŠµŠ¼ '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="403"/> + <source>Error reading replacement MBR file '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŃŃŠµŠ½ŠøŃ ŃŠ°Š¹Š»Š° Ń ŠæŠ¾Š“Š¼ŠµŠ½ŃŠµŠ¼ŃŠ¼ MBR '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="406"/> + <source>Out of memory reading '%s': %Rrc</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø ŠæŃŠø ŃŃŠµŠ½ŠøŠø '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="410"/> + <source>Replacement value file '%s' is to big: %Rhcb, max 16MiB</source> + <translation>Š¤Š°Š¹Š» Ń ŠæŠ¾Š“Š¼ŠµŠ½ŃŠµŠ¼ŃŠ¼ Š·Š½Š°ŃŠµŠ½ŠøŠµŠ¼ '%s' ŃŠ»ŠøŃŠŗŠ¾Š¼ Š±Š¾Š»ŃŃŠ¾Š¹: %Rhcb, Š¼Š°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ 16MiB</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="414"/> + <source>Cannot get the size of the value file '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ ŃŠ°Š¹Š»Š° '%s', ŃŠ¾Š“ŠµŃŠ¶Š°ŃŠøŠ¼ Š·Š½Š°ŃŠµŠ½ŠøŠµ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="433"/> + <location filename="../VBoxManageDisk.cpp" line="1060"/> + <location filename="../VBoxManageDisk.cpp" line="1245"/> + <location filename="../VBoxManageDisk.cpp" line="2585"/> + <source>Invalid medium variant '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²Š°ŃŠøŠ°Š½Ń Š½Š¾ŃŠøŃŠµŠ»Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="437"/> + <location filename="../VBoxManageDisk.cpp" line="799"/> + <location filename="../VBoxManageDisk.cpp" line="1069"/> + <location filename="../VBoxManageDisk.cpp" line="1261"/> + <location filename="../VBoxManageDisk.cpp" line="1680"/> + <location filename="../VBoxManageDisk.cpp" line="1796"/> + <location filename="../VBoxManageDisk.cpp" line="2008"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="443"/> + <location filename="../VBoxManageDisk.cpp" line="806"/> + <location filename="../VBoxManageDisk.cpp" line="1687"/> + <location filename="../VBoxManageDisk.cpp" line="1803"/> + <location filename="../VBoxManageDisk.cpp" line="2015"/> + <source>Invalid option -%c</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń Š¾ŠæŃŠøŃ -%c</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="445"/> + <location filename="../VBoxManageDisk.cpp" line="808"/> + <location filename="../VBoxManageDisk.cpp" line="1689"/> + <location filename="../VBoxManageDisk.cpp" line="1805"/> + <location filename="../VBoxManageDisk.cpp" line="2017"/> + <source>Invalid option case %i</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²Š°ŃŠøŠ°Š½Ń Š¾ŠæŃŠøŠø %i</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="448"/> + <location filename="../VBoxManageDisk.cpp" line="811"/> + <location filename="../VBoxManageDisk.cpp" line="1692"/> + <location filename="../VBoxManageDisk.cpp" line="1808"/> + <location filename="../VBoxManageDisk.cpp" line="2020"/> + <source>unknown option: %s +</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="452"/> + <location filename="../VBoxManageDisk.cpp" line="815"/> + <location filename="../VBoxManageDisk.cpp" line="1085"/> + <location filename="../VBoxManageDisk.cpp" line="1696"/> + <location filename="../VBoxManageDisk.cpp" line="1812"/> + <location filename="../VBoxManageDisk.cpp" line="2024"/> + <source>error: %Rrs</source> + <translation>Š¾ŃŠøŠ±ŠŗŠ°: %Rrs</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="463"/> + <location filename="../VBoxManageDisk.cpp" line="483"/> + <source>Parameters --filename is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --filename</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="465"/> + <source>Parameters --size is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --size</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="486"/> + <source>Creating a differencing medium is only supported for hard disks</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ ŃŠ°Š·Š½Š¾ŃŃŠ½Š¾Š³Š¾ Š½Š¾ŃŠøŃŠµŠ»Ń ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š“Š»Ń Š¶ŠµŃŃŠŗŠøŃ
Š“ŠøŃŠŗŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="505"/> + <source>Invalid parent hard disk reference, avoiding crash</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŃŃŃŠ»ŠŗŠ° Š½Š° ŃŠ¾Š“ŠøŃŠµŠ»ŃŃŠŗŠøŠ¹ Š¶ŠµŃŃŠŗŠøŠ¹ Š“ŠøŃŠŗ, ŠæŃŠµŠ“Š¾ŃŠ²ŃŠ°ŃŠµŠ½ŠøŠµ ŠŗŃŠ°Ń
Š°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="588"/> + <source>The %s is not found in the property list of the requested medium format.</source> + <translation>%s Š½Šµ Š½Š°Š¹Š“ŠµŠ½ Š² ŃŠæŠøŃŠŗŠµ ŃŠ²Š¾Š¹ŃŃŠ² Š·Š°ŠæŃŠ¾ŃŠµŠ½Š½Š¾Š³Š¾ ŃŠ¾ŃŠ¼Š°ŃŠ° Š½Š¾ŃŠøŃŠµŠ»Ń.</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="598"/> + <source>Base64 encoding of the property %s failed. (%Rhrc)</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠŗŠ¾Š“ŠøŃŠ¾Š²Š°ŃŃ ŃŠ²Š¾Š¹ŃŃŠ²Š¾, ŠøŃŠæŠ¾Š»ŃŠ·ŃŃ Base64. (%Rhrc)</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="622"/> + <source>Failed to create medium</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="630"/> + <source>Medium created. UUID: %s +</source> + <translation>ŠŠ¾ŃŠøŃŠµŠ»Ń ŃŠ¾Š·Š“Š°Š½. UUID: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="718"/> + <source>Invalid medium type '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ Š½Š¾ŃŠøŃŠµŠ»Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="725"/> + <source>Invalid autoreset parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ Š°Š²ŃŠ¾ŃŠ±ŃŠ¾ŃŠ° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="748"/> + <source>Invalid --property argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --property '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="755"/> + <source>Error: Failed to allocate memory for medium property '%s' +</source> + <translation>ŠŃŠøŠ±ŠŗŠ°: ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠ“ŠµŠ»ŠøŃŃ ŠæŠ°Š¼ŃŃŃ Š“Š»Ń ŃŠ²Š¾Š¹ŃŃŠ²Š° Š½Š¾ŃŠøŃŠµŠ»Ń '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="823"/> + <location filename="../VBoxManageDisk.cpp" line="1705"/> + <location filename="../VBoxManageDisk.cpp" line="1820"/> + <source>Medium name or UUID required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠøŠ¼Ń ŠøŠ»Šø UUID Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="834"/> + <source>No operation specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š° Š¾ŠæŠµŃŠ°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="855"/> + <source>Invalid medium reference, avoiding crash</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŃŃŃŠ»ŠŗŠ° Š½Š° Š½Š¾ŃŠøŃŠµŠ»Ń, ŠæŃŠµŠ“Š¾ŃŠ²ŃŠ°ŃŠµŠ½ŠøŠµ ŠŗŃŠ°Ń
Š°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="876"/> + <source>Error: Attempt to resize the medium from %RU64.%RU64 MB to %RU64.%RU64 MB. Use --resizebyte if this is intended! +</source> + <translation>ŠŃŠøŠ±ŠŗŠ°: ŠŠ¾ŠæŃŃŠŗŠ° ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠ°Š·Š¼ŠµŃ Š½Š¾ŃŠøŃŠµŠ»Ń Ń %RU64.%RU64 MB Š² %RU64.%RU64 MB. ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ --resizebyte, ŠµŃŠ»Šø ŃŃŠ¾ ŃŠ°Šŗ Šø Š“Š¾Š»Š¶Š½Š¾ Š±ŃŃŃ! +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="910"/> + <source>Compact medium operation is not implemented!</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŃ ŃŠ¶Š°ŃŠøŃ Š½Š¾ŃŠøŃŠµŠ»Ń Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="912"/> + <source>Compact medium operation for this format is not implemented yet!</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŃ ŃŠ¶Š°ŃŠøŃ Š½Š¾ŃŠøŃŠµŠ»Ń Š“Š»Ń ŃŃŠ¾Š³Š¾ ŃŠ¾ŃŠ¼Š°ŃŠ° ŠµŃŠµ Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="914"/> + <source>Failed to compact medium</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¶Š°ŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="916"/> + <source>Failed to compact medium!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¶Š°ŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="929"/> + <source>Failed to resize medium</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠ°Š·Š¼ŠµŃ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="931"/> + <source>Resize medium operation is not implemented!</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŃ ŃŠ°Š·Š¼ŠµŃŠ° Š½Š¾ŃŠøŃŠµŠ»Ń Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="933"/> + <source>Resize medium operation for this format is not implemented yet!</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŃ ŃŠ°Š·Š¼ŠµŃŠ° Š½Š¾ŃŠøŃŠµŠ»Ń Š“Š»Ń ŃŃŠ¾Š³Š¾ ŃŠ¾ŃŠ¼Š°ŃŠ° ŠµŃŠµ Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="935"/> + <source>Failed to resize medium!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠøŠ·Š¼ŠµŠ½ŠøŃŃ ŃŠ°Š·Š¼ŠµŃ Š½Š¾ŃŠøŃŠµŠ»Ń!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="951"/> + <source>Failed to move medium</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠµŃŠµŠ¼ŠµŃŃŠøŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="957"/> + <source>Move medium with UUID %s finished +</source> + <translation>ŠŠµŃŠµŠ¼ŠµŃŠµŠ½ŠøŠµ Š½Š¾ŃŠøŃŠµŠ»Ń Ń UUID %s Š·Š°ŠŗŠ¾Š½ŃŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="970"/> + <source>Set new location of medium with UUID %s finished +</source> + <translation>Š£ŃŃŠ°Š½Š¾Š²ŠŗŠ° Š½Š¾Š²Š¾Š³Š¾ Š¼ŠµŃŃŠ¾ŠæŠ¾Š»Š¾Š¶ŠµŠ½ŠøŃ Š½Š¾ŃŠøŃŠµŠ»Ń Ń UUID %s Š·Š°ŠŗŠ¾Š½ŃŠµŠ½Š° +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="977"/> + <source>Medium description has been changed. +</source> + <translation>ŠŠæŠøŃŠ°Š½ŠøŠµ Š½Š¾ŃŠøŃŠµŠ»Ń ŠøŠ·Š¼ŠµŠ½ŠµŠ½Š¾. +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1076"/> + <source>unhandled option: -%c</source> + <translation>Š½ŠµŠ¾Š±ŃŠ°Š±Š¾ŃŠ°Š½Š½Š°Ń Š¾ŠæŃŠøŃ: -%c</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1078"/> + <source>unhandled option: %i</source> + <translation>Š½ŠµŠ¾Š±ŃŠ°Š±Š¾ŃŠ°Š½Š½Š°Ń Š¾ŠæŃŠøŃ: %i</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1081"/> + <source>unknown option: %s</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1092"/> + <source>Mandatory UUID or input file parameter missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: ŠøŠ»Šø UUID ŠøŠ»Šø Š²Ń
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1094"/> + <source>Mandatory output file parameter missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: Š²ŃŃ
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1096"/> + <source>Specified options which cannot be used with --existing</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š° Š¾ŠæŃŠøŃ, ŠŗŠ¾ŃŠ¾ŃŠ°Ń Š½Šµ Š¼Š¾Š¶ŠµŃ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŃŃŃ Ń --existing</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1184"/> + <source>Failed to clone medium</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠŗŠ»Š¾Š½ŠøŃŠ¾Š²Š°ŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1189"/> + <source>Clone medium created in format '%ls'. UUID: %s +</source> + <translation>Š”Š¾Š·Š“Š°Š½ ŠŗŠ»Š¾Š½ŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ Š½Š¾ŃŠøŃŠµŠ»Ń Š² ŃŠ¾ŃŠ¼Š°ŃŠµ '%ls'. UUID: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1233"/> + <source>Invalid UUID '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ UUID '%s'</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1270"/> + <source>Incorrect number of parameters</source> + <translation>ŠŠµŠŗŠ¾ŃŃŠµŠŗŃŠ½Š¾Šµ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1271"/> + <source>Converting from raw image file="%s" to file="%s"... +</source> + <translation>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ ŠøŠ· ŃŠ°Š¹Š»Š° raw Š¾Š±ŃŠ°Š·Š° ="%s" Š² ŃŠ°Š¹Š» ="%s"... +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1293"/> + <source>Cannot open file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ ŃŠ°Š¹Š» "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1305"/> + <source>Cannot get image size for file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ Š¾Š±ŃŠ°Š·Š° Š“Š»Ń ŃŠ°Š¹Š»Š° "%s": %Rrc</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDisk.cpp" line="1309"/> + <source>Creating %s image with size %RU64 bytes (%RU64MB)... +</source> + <translation> + <numerusform>Š”Š¾Š·Š“Š°Š½ŠøŠµ %s Š¾Š±ŃŠ°Š·Š° ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹Ń (%RU64MB)... +</numerusform> + <numerusform>Š”Š¾Š·Š“Š°Š½ŠøŠµ %s Š¾Š±ŃŠ°Š·Š° ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹ŃŠ° (%RU64MB)... +</numerusform> + <numerusform>Š”Š¾Š·Š“Š°Š½ŠøŠµ %s Š¾Š±ŃŠ°Š·Š° ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹Ń (%RU64MB)... +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1518"/> + <source>fixed</source> + <translation>ŃŠøŠŗŃŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1516"/> + <source>dynamic</source> + <translation>Š“ŠøŠ½Š°Š¼ŠøŃŠµŃŠŗŠøŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1310"/> + <source>fixed</source> + <comment>adjective</comment> + <translation>ŃŠøŠŗŃŠøŃŠ¾Š²Š°Š½Š½Š¾Š³Š¾</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1310"/> + <source>dynamic</source> + <comment>adjective</comment> + <translation>Š“ŠøŠ½Š°Š¼ŠøŃŠµŃŠŗŠ¾Š³Š¾</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1313"/> + <source>Converted image from %s</source> + <translation>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ Š¾Š±ŃŠ°Š· ŠøŠ· %s</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1317"/> + <source>Cannot create the virtual disk container: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŠŗŠ¾Š½ŃŠµŠ¹Š½ŠµŃ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ°: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1335"/> + <source>Cannot create the disk image "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±ŃŠ°Š· Š“ŠøŃŠŗŠ° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1345"/> + <source>Out of memory allocating buffers for image "%s": %Rrc</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ Š±ŃŃŠµŃŠ¾Š² Š“Š»Ń Š¾Š±ŃŠ°Š·Š° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1364"/> + <source>Failed to write to disk image "%s": %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŠøŃŠ°ŃŃ Š² Š¾Š±ŃŠ°Š· Š“ŠøŃŠŗŠ° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1393"/> + <source>Parent UUID: %s +</source> + <translation>Š Š¾Š“ŠøŃŠµŠ»ŃŃŠŗŠøŠ¹ UUID: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1398"/> + <location filename="../VBoxManageDisk.cpp" line="1445"/> + <location filename="../VBoxManageDisk.cpp" line="1500"/> + <source>unknown</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1402"/> + <source>not created</source> + <translation>Š½Šµ ŃŠ¾Š·Š“Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1405"/> + <source>created</source> + <translation>ŃŠ¾Š·Š“Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1408"/> + <source>locked read</source> + <translation>Š·Š°Š±Š»Š¾ŠŗŠøŃŠ¾Š²Š°Š½ Š½Š° ŃŃŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1411"/> + <source>locked write</source> + <translation>Š·Š°Š±Š»Š¾ŠŗŠøŃŠ¾Š²Š°Š½ Š½Š° Š·Š°ŠæŠøŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1414"/> + <source>inaccessible</source> + <translation>Š½ŠµŠ“Š¾ŃŃŃŠæŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1417"/> + <source>creating</source> + <translation>ŃŠ¾Š·Š“Š°Š½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1420"/> + <source>deleting</source> + <translation>ŃŠ“Š°Š»ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1426"/> + <source>State: %s +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1432"/> + <source>Access Error: %ls +</source> + <translation>ŠŃŠøŠ±ŠŗŠ° Š“Š¾ŃŃŃŠæŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1440"/> + <source>Description: %ls +</source> + <translation>ŠŠæŠøŃŠ°Š½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1450"/> + <source>normal (differencing)</source> + <translation>Š½Š¾ŃŠ¼Š°Š»ŃŠ½ŃŠ¹ (ŃŠ°Š·Š½Š¾ŃŃŠ½ŃŠ¹)</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1452"/> + <source>normal (base)</source> + <translation>Š½Š¾ŃŠ¼Š°Š»ŃŠ½ŃŠ¹ (Š±Š°Š·Š¾Š²ŃŠ¹)</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1455"/> + <source>immutable</source> + <translation>Š½ŠµŠøŠ·Š¼ŠµŠ½ŃŠµŠ¼ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1458"/> + <source>writethrough</source> + <translation>ŃŠŗŠ²Š¾Š·Š½Š°Ń Š·Š°ŠæŠøŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1461"/> + <source>shareable</source> + <translation>ŃŠ°Š·Š“ŠµŠ»ŃŠµŠ¼ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1464"/> + <source>readonly</source> + <translation>ŃŠ¾Š»ŃŠŗŠ¾ Š“Š»Ń ŃŃŠµŠ½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1467"/> + <source>multiattach</source> + <translation>Š¼Š½Š¾Š¶ŠµŃŃŠ²ŠµŠ½Š½Š¾Šµ ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1473"/> + <source>Type: %s +</source> + <translation>Š¢ŠøŠæ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1480"/> + <source>Auto-Reset: %s +</source> + <translation>ŠŠ²ŃŠ¾ŃŠ±ŃŠ¾Ń: %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1480"/> + <source>on</source> + <translation>Š²ŠŗŠ»</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1480"/> + <source>off</source> + <translation>Š²ŃŠŗŠ»</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1485"/> + <source>Location: %ls +</source> + <translation>Š Š°ŃŠæŠ¾Š»Š¾Š¶ŠµŠ½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1489"/> + <source>Storage format: %ls +</source> + <translation>Š¤Š¾ŃŠ¼Š°Ń Ń
ŃŠ°Š½ŠµŠ½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1504"/> + <source>split2G</source> + <translation>ŠŠµŠ»ŠøŃŃ ŠæŠ¾ 2G</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1507"/> + <source>streamOptimized</source> + <translation>Š¾ŠæŃŠøŠ¼ŠøŠ·ŠøŃŠ¾Š²Š°Š½ Š“Š»Ń ŠæŠ¾ŃŠ¾ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1510"/> + <source>ESX</source> + <translation>ESX</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1513"/> + <source>default</source> + <translation>ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1520"/> + <source>differencing</source> + <translation>ŃŠ°Š·Š½Š¾ŃŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1521"/> + <source>Format variant: %s %s +</source> + <translation>ŠŠ°ŃŠøŠ°Š½Ń ŃŠ¾ŃŠ¼Š°ŃŠ°: %s %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1526"/> + <source>Capacity: %lld MBytes +</source> + <translation>ŠŠ¼ŠŗŠ¾ŃŃŃ: %lld MB +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1531"/> + <source>Size on disk: %lld MBytes +</source> + <translation>Š Š°Š·Š¼ŠµŃ Š½Š° Š“ŠøŃŠŗŠµ: %lld MB +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1539"/> + <source>Encryption: enabled +</source> + <translation>ŠØŠøŃŃŠ¾Š²Š°Š½ŠøŠµ: Š²ŠŗŠ»ŃŃŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1542"/> + <source>Cipher: %ls +</source> + <translation>ŠØŠøŃŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1543"/> + <source>Password ID: %ls +</source> + <translation>ID ŠæŠ°ŃŠ¾Š»Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1547"/> + <source>Encryption: disabled +</source> + <translation>ŠØŠøŃŃŠ¾Š²Š°Š½ŠøŠµ: Š²ŃŠŗŠ»ŃŃŠµŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1563"/> + <source>Property: </source> + <translation>Š”Š²Š¾Š¹ŃŃŠ²Š¾: </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1584"/> + <source>In use by VMs: </source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·ŃŠµŃŃŃ Š² ŠŠ: </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1619"/> + <source>Child UUIDs: </source> + <translation>ŠŠ¾ŃŠµŃŠ½ŠøŠµ UUID: </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1725"/> + <source>base</source> + <translation>Š±Š°Š·Š¾Š²ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1845"/> + <source>Failed to delete medium</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1848"/> + <source>Failed to delete medium. Error code %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń. ŠŠ¾Š“ Š¾ŃŠøŠ±ŠŗŠø %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1884"/> + <source>unexpected parameter %s +</source> + <translation>Š½ŠµŠ¾Š¶ŠøŠ“Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ %s +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1897"/> + <source>Missing action</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š“ŠµŠ¹ŃŃŠ²ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1903"/> + <source>Invalid action given: %s</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š¾ Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š“ŠµŠ¹ŃŃŠ²ŠøŠµ: %s</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1909"/> + <source>Invalid number of arguments given for action: %s</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŃŠøŃŠ»Š¾ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ¾Š², ŃŠŗŠ°Š·Š°Š½Š½Š¾Šµ Š“Š»Ń Š“ŠµŠ¹ŃŃŠ²ŠøŃ: %s</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2029"/> + <source>Disk name or UUID required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠøŠ¼Ń ŠøŠ»Šø UUID Š“ŠøŃŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2032"/> + <source>No password specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŠæŠ°ŃŠ¾Š»Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2036"/> + <source>A new password must always have a valid identifier set at the same time</source> + <translation>ŠŠ¾Š²ŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń Š“Š¾Š»Š¶ŠµŠ½ Š²ŃŠµŠ³Š“Š° ŠøŠ¼ŠµŃŃ Š“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŃŠ½ŃŠ¹ ŠøŠ“ŠµŠ½ŃŠøŃŠøŠŗŠ°ŃŠ¾Ń Š·Š°Š“Š°Š½Š½ŃŠ¹ Š² ŃŠ¾ Š¶Šµ Š²ŃŠµŠ¼Ń</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2043"/> + <source>Enter new password:</source> + <translation>ŠŠ²ŠµŠ“ŠøŃŠµ Š½Š¾Š²ŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2052"/> + <source>Failed to read new password from file</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ Š½Š¾Š²ŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń ŠøŠ· ŃŠ°Š¹Š»Š°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2063"/> + <source>Enter old password:</source> + <translation>ŠŠ²ŠµŠ“ŠøŃŠµ ŃŃŠ°ŃŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2072"/> + <source>Failed to read old password from file</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ ŃŃŠ°ŃŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń ŠøŠ· ŃŠ°Š¹Š»Š°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2085"/> + <location filename="../VBoxManageDisk.cpp" line="2144"/> + <source>Invalid hard disk reference, avoiding crash</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŃŃŃŠ»ŠŗŠ° Š½Š° Š¶ŠµŃŃŠŗŠøŠ¹ Š“ŠøŃŠŗ, ŠæŃŠµŠ“Š¾ŃŠ²ŃŠ°ŃŠµŠ½ŠøŠµ ŠŗŃŠ°Ń
Š°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2096"/> + <source>Encrypt hard disk operation is not implemented!</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŃ ŃŠøŃŃŠ¾Š²Š°Š½ŠøŃ Š¶ŠµŃŃŠŗŠ¾Š³Š¾ Š“ŠøŃŠŗŠ° Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2098"/> + <source>Encrypt hard disk operation for this cipher is not implemented yet!</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŃ ŃŃŠøŃŠ¾Š²Š°Š½ŠøŃ Š¶ŠµŃŃŠŗŠ¾Š³Š¾ Š“ŠøŃŠŗŠ° Š“Š»Ń ŃŃŠ¾Š³Š¾ ŃŠøŃŃŠ° ŠµŃŠµ Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2100"/> + <source>Failed to encrypt hard disk</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŃŠøŃŃŠ¾Š²Š°ŃŃ Š¶ŠµŃŃŠŗŠøŠ¹ Š“ŠøŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2102"/> + <source>Failed to encrypt hard disk!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŃŠøŃŃŠ¾Š²Š°ŃŃ Š¶ŠµŃŃŠŗŠøŠ¹ Š“ŠøŃŠŗ!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2116"/> + <source>Invalid number of arguments: %d</source> + <translation>ŠŠµŠæŃŠ°Š²ŠøŠ»ŃŠ½Š¾Šµ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ¾Š²: %d</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2123"/> + <source>Enter password:</source> + <translation>ŠŠ²ŠµŠ“ŠøŃŠµ ŠæŠ°ŃŠ¾Š»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2132"/> + <source>Failed to read password from file</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ ŠæŠ°ŃŠ¾Š»Ń ŠøŠ· ŃŠ°Š¹Š»Š°</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2148"/> + <source>The given password is correct +</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŠæŠ°ŃŠ¾Š»Ń - ŠŗŠ¾ŃŃŠµŠŗŃŠ½ŃŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2226"/> + <source>No medium specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ Š½Š¾ŃŠøŃŠµŠ»Ń!</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2237"/> + <source>Enter encryption password:</source> + <translation>ŠŠ²ŠµŠ“ŠøŃŠµ ŠæŠ°ŃŠ¾Š»Ń Š“Š»Ń ŃŠøŃŃŠ¾Š²Š°Š½ŠøŃ:</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2389"/> + <location filename="../VBoxManageDisk.cpp" line="2610"/> + <source>Error opening '%s' for writing: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŠŗŃŃŃŃ '%s' Š“Š»Ń Š·Š°ŠæŠøŃŠø: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2405"/> + <source>Specified offset (%#RX64) is beyond the end of the medium (%#RX64)</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š½Š°Ń ŠæŠ¾Š·ŠøŃŠøŃ (%#RX64) Š²ŃŃ
Š¾Š“ŠøŃ Š·Š° Š³ŃŠ°Š½ŠøŃŃ Š½Š¾ŃŠøŃŠµŠ»Ń (%#RX64)</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDisk.cpp" line="2435"/> + <source>Read(%zu bytes at %#RX64)</source> + <translation> + <numerusform>Š§ŃŠµŠ½ŠøŠµ (%zu Š±Š°Š¹Ń, ŠæŠ¾Š·ŠøŃŠøŃ %#RX64)</numerusform> + <numerusform>Š§ŃŠµŠ½ŠøŠµ (%zu Š±Š°Š¹ŃŠ°, ŠæŠ¾Š·ŠøŃŠøŃ %#RX64)</numerusform> + <numerusform>Š§ŃŠµŠ½ŠøŠµ (%zu Š±Š°Š¹Ń, ŠæŠ¾Š·ŠøŃŠøŃ %#RX64)</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2464"/> + <source>********** <ditto x %RU64> +</source> + <translation>********** <ŃŠ¾ Š¶Šµ ŃŠ°Š¼Š¾Šµ x %RU64> +</translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2513"/> + <location filename="../VBoxManageDisk.cpp" line="2654"/> + <source>Error writing to '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø Š·Š°ŠæŠøŃŠø Š² '%s': %Rrc</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDisk.cpp" line="2521"/> + <source>Expected read() at offset %RU64 (%#RX64) to return %#zx bytes, only got %#zx! +</source> + <translation> + <numerusform>ŠŠ¶ŠøŠ“Š°Š»Š¾ŃŃ read() Ń ŠæŠ¾Š·ŃŠøŠø %RU64 (%#RX64) ŠæŃŠ¾ŃŠøŃŠ°ŃŃ %#zx Š±Š°Š¹Ń, ŠæŠ¾Š»ŃŃŠµŠ½Š¾ ŃŠ¾Š»ŃŠŗŠ¾ %#zx! +</numerusform> + <numerusform>ŠŠ¶ŠøŠ“Š°Š»Š¾ŃŃ read() Ń ŠæŠ¾Š·ŃŠøŠø %RU64 (%#RX64) ŠæŃŠ¾ŃŠøŃŠ°ŃŃ %#zx Š±Š°Š¹ŃŠ°, ŠæŠ¾Š»ŃŃŠµŠ½Š¾ ŃŠ¾Š»ŃŠŗŠ¾ %#zx! +</numerusform> + <numerusform>ŠŠ¶ŠøŠ“Š°Š»Š¾ŃŃ read() Ń ŠæŠ¾Š·ŃŠøŠø %RU64 (%#RX64) ŠæŃŠ¾ŃŠøŃŠ°ŃŃ %#zx Š±Š°Š¹Ń, ŠæŠ¾Š»ŃŃŠµŠ½Š¾ ŃŠ¾Š»ŃŠŗŠ¾ %#zx! +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2537"/> + <location filename="../VBoxManageDisk.cpp" line="2675"/> + <source>Error closing '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø Š·Š°ŠŗŃŃŃŠøŠø '%s': %Rrc</translation> + </message> +</context> +<context> + <name>GuestCtrl</name> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="276"/> + <source>Unable to install console control handler, rc=%Rrc +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŃŃŠ°Š½Š¾Š²ŠøŃŃ Š¾Š±ŃŠ°Š±Š¾ŃŃŠøŠŗ ŃŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠŗŠ¾Š½ŃŠ¾Š»Šø, rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="303"/> + <source>Unable to uninstall console control handler, rc=%Rrc +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ“Š°Š»ŠøŃŃ Š¾Š±ŃŠ°Š±Š¾ŃŃŠøŠŗ ŃŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠŗŠ¾Š½ŃŠ¾Š»Šø, rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="332"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="398"/> + <source>starting</source> + <translation>Š·Š°ŠæŃŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="334"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="367"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="400"/> + <source>started</source> + <translation>Š·Š°ŠæŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="336"/> + <source>paused</source> + <translation>ŠæŃŠøŠ¾ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="338"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="402"/> + <source>terminating</source> + <translation>Š·Š°Š²ŠµŃŃŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="340"/> + <source>successfully terminated</source> + <translation>ŃŃŠæŠµŃŠ½Š¾ Š·Š°Š²ŠµŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="342"/> + <source>terminated by signal</source> + <translation>Š·Š°Š²ŠµŃŃŠµŠ½ ŠæŠ¾ ŃŠøŠ³Š½Š°Š»Ń</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="344"/> + <source>abnormally aborted</source> + <translation>Š½ŠµŠ½Š¾ŃŠ¼Š°Š»ŃŠ½Š¾ ŠæŃŠµŃŠ²Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="346"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="375"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="406"/> + <source>timed out</source> + <translation>ŠæŃŠµŠ²ŃŃŠµŠ½Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="348"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="408"/> + <source>timed out, hanging</source> + <translation>ŠæŃŠµŠ²ŃŃŠµŠ½Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ, Š·Š°Š²ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="350"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="410"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="435"/> + <source>killed</source> + <translation>ŃŠ±ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="352"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="373"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="412"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="437"/> + <source>error</source> + <translation>Š¾ŃŠøŠ±ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="356"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="387"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="416"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="441"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="451"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="464"/> + <source>unknown</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="369"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="404"/> + <source>terminated</source> + <translation>Š·Š°Š²ŠµŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="371"/> + <source>status changed</source> + <translation>ŃŃŠ°ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="377"/> + <source>stdin ready</source> + <translation>stdin Š³Š¾ŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="379"/> + <source>data on stdout</source> + <translation>Š“Š°Š½Š½ŃŠµ Š² stdout</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="381"/> + <source>data on stderr</source> + <translation>Š“Š°Š½Š½ŃŠµ Š² stderr</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="383"/> + <source>waiting flag not supported</source> + <translation>ŃŠ»Š°Š³ Š¾Š¶ŠøŠ“Š°Š½ŠøŃ Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="427"/> + <source>opening</source> + <translation>Š¾ŃŠŗŃŃŠ²Š°ŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="429"/> + <source>open</source> + <translation>Š¾ŃŠŗŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="431"/> + <source>closing</source> + <translation>Š·Š°ŠŗŃŃŠ²Š°ŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="433"/> + <source>closed</source> + <translation>Š·Š°ŠŗŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="452"/> + <source>fifo</source> + <translation>fifo</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="453"/> + <source>char-device</source> + <translation>ŃŠøŠ¼Š²Š¾Š»ŃŠ½Š¾Šµ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="454"/> + <source>directory</source> + <translation>Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="455"/> + <source>block-device</source> + <translation>Š±Š»Š¾ŃŠ½Š¾Šµ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="456"/> + <source>file</source> + <translation>ŃŠ°Š¹Š»</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="457"/> + <source>symlink</source> + <translation>ŃŠøŠ²Š¾Š»ŠøŃŠµŃŠŗŠ°Ń ŃŃŃŠ»ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="458"/> + <source>socket</source> + <translation>ŃŠ¾ŠŗŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="459"/> + <source>white-out</source> + <translation>white-out</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="478"/> + <source>Error details:</source> + <translation>ŠŠ¾Š“ŃŠ¾Š±Š½Š¾ŃŃŠø Š¾ŃŠøŠ±ŠŗŠø:</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="483"/> + <source>Object has indicated no error (%Rhrc)!? +</source> + <translation>ŠŠ±ŃŠµŠŗŃ Š½Šµ ŠæŠ¾ŠŗŠ°Š·Š°Š» Š¾ŃŠøŠ±ŠŗŠø (%Rhrc)!? +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="515"/> + <source>Could not lookup progress information +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾ ŠæŃŠ¾Š³ŃŠµŃŃŠµ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="574"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3247"/> + <source>Out of memory</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="602"/> + <source>The --username|-u option is ignored by '%s'</source> + <translation>ŠŠæŃŠøŃ --username|-u ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="609"/> + <source>Password is given more than once.</source> + <translation>ŠŠ°ŃŠ¾Š»Ń ŃŠŗŠ°Š·Š°Š½ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="613"/> + <source>The --password option is ignored by '%s'</source> + <translation>ŠŠæŃŠøŃ --password ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="620"/> + <source>The --password-file|-p option is ignored by '%s'</source> + <translation>ŠŠæŃŠøŃ --password-file|-p ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="627"/> + <source>The --domain option is ignored by '%s'</source> + <translation>ŠŠæŃŠø --domain ŠæŃŠ¾ŠøŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°Š½Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="692"/> + <source>Failed to get a IConsole pointer for the machine. Is it still running? +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠŗŠ°Š·Š°ŃŠµŠ»Ń Š½Š° IConsole Š“Š»Ń Š¼Š°ŃŠøŠ½Ń. ŠŠ½Š° Š²ŃŠµ ŠµŃŠµ ŃŠ°Š±Š¾ŃŠ°ŠµŃ? +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="697"/> + <source>Machine "%s" is not running (currently %s)! +</source> + <translation>ŠŠ°ŃŠøŠ½Š° "%s" Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š° (ŃŠµŠŗŃŃŠøŠ¹: %s)! +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="726"/> + <source>[%RU32] VBoxManage Guest Control [%s] - %s</source> + <translation>[%RU32] VBoxManage ŠŠ¾ŃŃŠµŠ²Š¾Šµ Š£ŠæŃŠ°Š²Š»ŠµŠ½ŠøŠµ [%s] - %s</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="728"/> + <source>No enough memory for session name</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°Š¼ŃŃŠø Š“Š»Ń ŠøŠ¼ŠµŠ½Šø ŃŠµŃŃŠøŠø</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="734"/> + <source>Creating guest session as user '%s'... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠµŃŃŠøŠø ŠæŠ¾Š“ ŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»ŠµŠ¼ '%s'... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="745"/> + <source>Out of memory setting up IGuest::CreateSession call</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø Š“Š»Ń Š½Š°ŃŃŃŠ¾Š¹ŠŗŠø Š²ŃŠ·Š¾Š²Š° IGuest::CreateSession</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="754"/> + <source>Waiting for guest session to start... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ ŃŃŠ°ŃŃŠ° Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠµŃŃŠøŠø... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="766"/> + <source>Out of memory setting up IGuestSession::WaitForArray call</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø Š“Š»Ń Š½Š°ŃŃŃŠ¾Š¹ŠŗŠø Š²ŃŠ·Š¾Š²Š° IGuestSession::WaitForArray</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="782"/> + <source>Successfully started guest session (ID %RU32) +</source> + <translation>Š£ŃŠæŠµŃŠ½Š¾ Š·Š°ŠæŃŃŠµŠ½Š° Š³Š¾ŃŃŠµŠ²Š°Ń ŃŠµŃŃŠøŃ (ID %RU32) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="791"/> + <source>Error starting guest session (current status is: %s) +</source> + <translation>ŠŃŠøŠ±ŠŗŠ° Š²Š¾ Š²ŃŠµŠ¼Ń ŃŃŠ°ŃŃŠ° Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠµŃŃŠøŠø (ŃŠµŠŗŃŃŠøŠ¹ ŃŃŠ°ŃŃŃ: %s) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="792"/> + <source><unknown></source> + <translation><Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="851"/> + <source>No user name specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»Ń!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="891"/> + <source>Closing guest session ... +</source> + <translation>ŠŠ°ŠŗŃŃŃŠøŠµ Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠµŃŃŠøŠø ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="897"/> + <source>Guest session detached +</source> + <translation>ŠŠ¾ŃŃŠµŠ²Š°Ń ŃŠµŃŃŠøŃ Š¾ŃŃŠ¾ŠµŠ“ŠøŠ½ŠµŠ½Š° +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1058"/> + <source>Unable to write output, rc=%Rrc +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š·Š°ŠæŠøŃŠ°ŃŃ Š²ŃŃ
Š¾Š“Š½Š¾Š¹ ŠæŠ¾ŃŠ¾Šŗ, rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1088"/> + <source>Unsupported %s line ending conversion</source> + <translation>ŠŠµŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼Š¾Šµ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ %s Š·Š°Š²ŠµŃŃŠµŠ½ŠøŃ ŃŃŃŠ¾ŠŗŠø</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1093"/> + <source>Error getting %s handle: %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŠæŠ¾Š»ŃŃŠµŠ½ŠøŠø %s Š¾Š±ŃŠ°Š±Š¾ŃŃŠøŠŗŠ°: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1216"/> + <source>Invalid argument variable[=value]: '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠæŠµŃŠµŠ¼ŠµŠ½Š½Š°Ń Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ°[=Š·Š½Š°ŃŠµŠ½ŠøŠµ]: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1226"/> + <source>Warning: Deprecated option "--no-profile" specified +</source> + <translation>ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: Š£ŠŗŠ°Š·Š°Š½Š° ŃŃŃŠ°ŃŠµŠ²ŃŠ°Ń Š¾ŠæŃŠøŃ "--no-profile" +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1292"/> + <source>No executable specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ Š²ŃŠæŠ¾Š»Š½ŃŠµŠ¼ŃŠ¹ ŃŠ°Š¹Š»!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1344"/> + <source>Starting guest process ... +</source> + <translation>Š”ŃŠ°ŃŃ Š³Š¾ŃŃŠµŠ²Š¾Š³Š¾ ŠæŃŠ¾ŃŠµŃŃŠ°... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1346"/> + <source>Starting guest process (within %ums) +</source> + <translation>Š”ŃŠ°ŃŃ Š³Š¾ŃŃŠµŠ²Š¾Š³Š¾ ŠæŃŠ¾ŃŠµŃŃŠ° (Š² ŃŠµŃŠµŠ½ŠøŠµ %u Š¼ŃŠµŠŗ) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1368"/> + <source>Process '%s' (PID %RU32) started +</source> + <translation>ŠŃŠ¾ŃŠµŃŃ '%s' (PID %RU32) Š·Š°ŠæŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1373"/> + <source>[%RU32 - Session %RU32] +</source> + <translation>[%RU32 - Š”ŠµŃŃŠøŃ %RU32] +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1394"/> + <source>waitResult: %d +</source> + <translation>ŃŠµŠ·ŃŠ»ŃŃŠ°Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ: %d +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1410"/> + <source>Process terminated +</source> + <translation>ŠŃŠ¾ŃŠµŃŃ Š·Š°Š²ŠµŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1487"/> + <source>Process execution aborted! +</source> + <translation>ŠŃŠæŠ¾Š»Š½ŠµŠ½ŠøŠµ ŠæŃŠ¾ŃŠµŃŃŠ° ŠæŃŠµŃŠ²Š°Š½Š¾! +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1493"/> + <source>Process successfully started! +</source> + <translation>ŠŃŠ¾ŃŠµŃŃ ŃŃŠæŠµŃŠ½Š¾ Š·Š°ŠæŃŃŠµŠ½! +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1507"/> + <source>Exit code=%u (Status=%u [%s]) +</source> + <translation>ŠŠ¾Š“ Š²ŃŃ
Š¾Š“Š° =%u (Š”ŃŠ°ŃŃŃ =%u [%s]) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1516"/> + <source>Process timed out (guest side) and %s +</source> + <translation>ŠŃŠµŠ²ŃŃŠµŠ½Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ ŠæŃŠ¾ŃŠµŃŃŠ° (Š³Š¾ŃŃŠµŠ²Š°Ń ŃŃŠ¾ŃŠ¾Š½Š°) Šø %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1518"/> + <source>failed to terminate so far</source> + <translation>Š½Šµ ŃŠ“Š°Š»Š¾ŃŃ Š“Š¾ ŃŠøŃ
ŠæŠ¾Ń Š·Š°Š²ŠµŃŃŠøŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1518"/> + <source>was terminated</source> + <translation>Š·Š°Š²ŠµŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1524"/> + <source>Process now is in status [%s] (unexpected) +</source> + <translation>Š”ŠµŠ¹ŃŠ°Ń ŠæŃŠ¾ŃŠµŃŃ Š² ŃŃŠ°ŃŃŃŠµ [%s] (Š½ŠµŠ¾Š¶ŠøŠ“Š°Š½Š½Š¾) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1532"/> + <source>Process monitor loop quit with vrc=%Rrc +</source> + <translation>Š¦ŠøŠŗŠ» Š½Š°Š±Š»ŃŠ“ŠµŠ½ŠøŃ Š·Š° ŠæŃŠ¾ŃŠµŃŃŠ¾Š¼ Š·Š°ŠŗŠ¾Š½ŃŠøŠ»ŃŃ Ń vrc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1538"/> + <source>Process monitor loop timed out +</source> + <translation>ŠŃŠµŠ²ŃŃŠµŠ½Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ Š² ŃŠøŠŗŠ»Šµ Š½Š°Š±Š»ŃŠ“ŠµŠ½ŠøŃ Š·Š° ŠæŃŠ¾ŃŠµŃŃŠ¾Š¼ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1641"/> + <source>No sources specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŠøŃŃŠ¾ŃŠ½ŠøŠŗ!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1649"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="2201"/> + <source>No destination specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŠµ!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1658"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1762"/> + <source>RTPathAbs failed on '%s': %Rrc</source> + <translation>RTPathAbs Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1671"/> + <source>Copying from host to guest ... +</source> + <translation>ŠŠ¾ŠæŠøŃŠ¾Š²Š°Š½ŠøŠµ ŠøŠ· Ń
Š¾ŃŃŠ° Š² Š³Š¾ŃŃŠµŠ²ŃŃ ŃŠøŃŃŠµŠ¼Ń... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1673"/> + <source>Copying from guest to host ... +</source> + <translation>ŠŠ¾ŠæŠøŃŠ¾Š²Š°Š½ŠøŠµ ŠøŠ· Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń Š² Ń
Š¾ŃŃ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1735"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1796"/> + <source>File '%s' -> '%s' +</source> + <translation>Š¤Š°Š¹Š» '%s' -> '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1744"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1782"/> + <source>Directory '%s' -> '%s' +</source> + <translation>ŠŠøŃŠµŠŗŃŠ¾ŃŠøŃ '%s' -> '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1756"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1805"/> + <source>Not a file or directory: %s +</source> + <translation>ŠŠµ ŃŠ°Š¹Š» Šø Š½Šµ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1685"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1759"/> + <source>RTPathQueryInfo failed on '%s': %Rrc</source> + <translation>RTPathQueryInfo Š·Š°Š²ŠµŃŃŠµŠ½ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1703"/> + <source>Destination must be a directory!</source> + <translation>ŠŠ°Š·Š½Š°ŃŠµŠ½ŠøŠµ Š“Š¾Š»Š¶Š½Š¾ Š±ŃŃŃ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠµŠ¹!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1811"/> + <source>FsObjQueryInfo failed on '%s': %Rhrc</source> + <translation>FsObjQueryInfo Š·Š°Š²ŠµŃŃŠµŠ½ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rhrc</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1825"/> + <source>File copy failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠŗŠ¾ŠæŠøŃŠ¾Š²Š°ŃŃ ŃŠ°Š¹Š»</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="1894"/> + <source>Creating %RU32 directories... +</source> + <translation> + <numerusform>Š”Š¾Š·Š“Š°Š½ŠøŠµ %RU32 Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø... +</numerusform> + <numerusform>Š”Š¾Š·Š“Š°Š½ŠøŠµ %RU32 Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + <numerusform>Š”Š¾Š·Š“Š°Š½ŠøŠµ %RU32 Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1898"/> + <source>mkdir was interrupted by Ctrl-C (%u left) +</source> + <translation>mkdir ŠæŃŠµŃŠ²Š°Š½ ŃŠµŃŠµŠ· Ctrl-C (%u Š¾ŃŃŠ°Š»Š¾ŃŃ) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1911"/> + <source>Creating directory "%s" ... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø "%s" ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1922"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="2006"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="2127"/> + <source>Out of memory +</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1932"/> + <source>No directory to create specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š° Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŃ Š“Š»Ń ŃŠ¾Š·Š“Š°Š½ŠøŃ!</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="1980"/> + <source>Removing %RU32 directory tree(s)... +</source> + <translation> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 Š“ŠµŃŠµŠ²Š° Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 Š“ŠµŃŠµŠ²ŃŠµŠ² Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 Š“ŠµŃŠµŠ²ŃŠµŠ² Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="1983"/> + <source>Removing %RU32 directorie(s)... +</source> + <translation> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø... +</numerusform> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠ¹... +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1988"/> + <source>rmdir was interrupted by Ctrl-C (%u left) +</source> + <translation>rmdir ŠæŃŠµŃŠ²Š°Š½ ŃŠµŃŠµŠ· Ctrl-C (%u Š¾ŃŃŠ°Š»Š¾ŃŃ) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1999"/> + <source>Removing directory "%s" ... +</source> + <translation>Š£Š“Š°Š»ŠµŠ½ŠøŠµ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø "%s" ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2018"/> + <source>Recursively removing directory "%s" ... +</source> + <translation>Š ŠµŠŗŃŃŃŠøŠ²Š½Š¾Šµ ŃŠ“Š°Š»ŠµŠ½ŠøŠµ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø "%s" ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2036"/> + <source>Directory deletion failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2042"/> + <source>Out of memory during recursive rmdir +</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø Š“Š»Ń ŃŠµŠŗŃŃŃŠøŠ²Š½Š¾Š³Š¾ rmdir +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2060"/> + <source>No directory to remove specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š° Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŃ Š“Š»Ń ŃŠ“Š°Š»ŠµŠ½ŠøŃ!</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="2100"/> + <source>Removing %RU32 file(s)... +</source> + <translation> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 ŃŠ°Š¹Š»Š°... +</numerusform> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 ŃŠ°Š¹Š»Š¾Š²... +</numerusform> + <numerusform>Š£Š“Š°Š»ŠµŠ½ŠøŠµ %RU32 ŃŠ°Š¹Š»Š¾Š²... +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2104"/> + <source>rm was interrupted by Ctrl-C (%u left) +</source> + <translation>rm ŠæŃŠµŃŠ²Š°Š½ ŃŠµŃŠµŠ· Ctrl-C (%u Š¾ŃŃŠ°Š»Š¾ŃŃ) +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2115"/> + <source>Removing file "%s" ... +</source> + <translation>Š£Š“Š°Š»ŠµŠ½ŠøŠµ ŃŠ°Š¹Š»Š° "%s" ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2137"/> + <source>No file to remove specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŃŠ°Š¹Š» Š“Š»Ń ŃŠ“Š°Š»ŠµŠ½ŠøŃ!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2195"/> + <source>Failed to initialize, rc=%Rrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·ŠøŃŠ¾Š²Š°ŃŃ, rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2199"/> + <source>No source(s) to move specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŠøŃŃŠ¾ŃŠ½ŠøŠŗ(Šø) Š“Š»Ń ŠæŠµŃŠµŠ¼ŠµŃŠµŠ½ŠøŃ!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2220"/> + <source>Destination does not exist +</source> + <translation>ŠŠ°Š·Š½Š°ŃŠµŠ½ŠøŠµ Š½Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2230"/> + <source>Destination must be a directory when specifying multiple sources +</source> + <translation>ŠŠ°Š·Š½Š°ŃŠµŠ½ŠøŠµ Š“Š¾Š»Š¶Š½Š¾ Š±ŃŃŃ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠµŠ¹ ŠŗŠ¾Š³Š“Š° ŃŠŗŠ°Š·ŃŠ²Š°ŃŃŃŃ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ¾Š² +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2234"/> + <source>Unable to determine destination type: %Rhrc +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŠæŃŠµŠ“ŠµŠ»ŠøŃŃ ŃŠøŠæ Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2243"/> + <source>Renaming %RU32 %s ... +</source> + <translation>ŠŠµŃŠµŠøŠ¼ŠµŠ½Š¾Š²Š°Š½ŠøŠµ %RU32 %s ... +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="2244"/> + <source>sources</source> + <translation> + <numerusform>ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°</numerusform> + <numerusform>ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ¾Š²</numerusform> + <numerusform>ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ¾Š²</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2244"/> + <source>source</source> + <translation>ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2259"/> + <source>Cannot stat "%s": No such file or directory +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ "%s": ŠŠµŃ ŃŠ°ŠŗŠ¾Š³Š¾ ŃŠ°Š¹Š»Š° ŠøŠ»Šø Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2276"/> + <source>Renaming %s "%s" to "%s" ... +</source> + <translation>ŠŠµŃŠµŠøŠ¼ŠµŠ½Š¾Š²Š°Š½ŠøŠµ %s "%s" Š² "%s" ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2277"/> + <source>directory</source> + <comment>object</comment> + <translation>Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2277"/> + <source>file</source> + <comment>object</comment> + <translation>ŃŠ°Š¹Š»Š°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2296"/> + <source>Warning: Not all sources were renamed +</source> + <translation>ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: ŠŠµ Š²ŃŠµ ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠø ŠæŠµŃŠµŠøŠ¼ŠµŠ½Š¾Š²Š°Š½Ń +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2355"/> + <source>More than one template specified! +</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š¾ Š±Š¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°Š±Š»Š¾Š½Š°! +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2364"/> + <source>No template specified!</source> + <translation>ŠØŠ°Š±Š»Š¾Š½Ń Š½Šµ ŃŠŗŠ°Š·Š°Š½Ń!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2367"/> + <source>Creating temporary files is currently not supported!</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š²ŃŠµŠ¼ŠµŠ½Š½ŃŃ
ŃŠ°Š¹Š»Š¾Š² ŃŠµŠ¹ŃŠ°Ń Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2379"/> + <source>Creating temporary directory from template '%s' in directory '%s' ... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø ŠøŠ· ŃŠ°Š±Š»Š¾Š½Š° '%s' Š² Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø '%s' ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2382"/> + <source>Creating temporary directory from template '%s' in default temporary directory ... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø ŠøŠ· ŃŠ°Š±Š»Š¾Š½Š° '%s' Š²Š¾ Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2385"/> + <source>Creating temporary file from template '%s' in directory '%s' ... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š²ŃŠ¼ŠµŠ½Š½Š¾Š³Š¾ ŃŠ°Š¹Š»Š° ŠøŠ· ŃŠ°Š±Š»Š¾Š½Š° '%s' Š² Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø '%s' ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2388"/> + <source>Creating temporary file from template '%s' in default temporary directory ... +</source> + <translation>Š”Š¾Š·Š“Š°Š½ŠøŠµ Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š³Š¾ ŃŠ°Š¹Š»Š° ŠøŠ· ŃŠ°Š±Š»Š¾Š½Š° '%s' Š²Š¾ Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2401"/> + <source>Directory name: %ls +</source> + <translation>ŠŠ¼Ń Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŠø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2444"/> + <source>Command "%s" not implemented yet!</source> + <translation>ŠŠ¾Š¼Š°Š½Š“Š° "%s" ŠµŃŠµ Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Š°!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2452"/> + <source>Nothing to stat!</source> + <translation>ŠŠµŃ Š¾Š±ŃŠµŠŗŃŠ° Š“Š»Ń Š·Š°ŠæŃŠ¾ŃŠ° ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŠø!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2465"/> + <source>Checking for element "%s" ... +</source> + <translation>ŠŃŠ¾Š²ŠµŃŠŗŠ° ŃŠ»ŠµŠ¼ŠµŠ½ŃŠ° "%s" ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2475"/> + <source>Failed to stat '%s': No such file +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š“Š»Ń '%s': ŠŠµŃ ŃŠ°ŠŗŠ¾Š³Š¾ ŃŠ°Š¹Š»Š° +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2480"/> + <source> File: '%s' +</source> + <translation> Š¤Š°Š¹Š»: '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2515"/> + <source> Size: %-17RU64 Alloc: %-19RU64 Type: %s +</source> + <translation> Š Š°Š·Š¼ŠµŃ: %-17RU64 ŠŃŠ“ŠµŠ»ŠµŠ½Š¾: %-19RU64 Š¢ŠøŠæ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2517"/> + <source>Device: %#-17RX32 INode: %-18RU64 Links: %u +</source> + <translation>Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š¾: %#-17RX32 INode: %-18RU64 Š”ŃŃŠ»ŠŗŠø: %u +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2528"/> + <source> Mode: %-16s Attrib: %-17s Dev ID: %#RX32 +</source> + <translation> Š ŠµŠ¶ŠøŠ¼: %-16s ŠŃŃŃŠøŠ±ŃŃŃ: %-17s ID ŃŃŃŃŠ¾Š¹ŃŃŠ²Š°: %#RX32 +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2530"/> + <source> Mode: %-16s Attrib: %s +</source> + <translation> Š ŠµŠ¶ŠøŠ¼: %-16s ŠŃŃŃŠøŠ±ŃŃŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2532"/> + <source> Owner: %4d/%-12ls Group: %4d/%ls +</source> + <translation> ŠŠ»Š°Š“ŠµŠ»ŠµŃ: %4d/%-12ls ŠŃŃŠæŠæŠ°: %4d/%ls +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2536"/> + <source> Birth: %s +</source> + <translation> Š”Š¾Š·Š“Š°Š½: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2538"/> + <source>Change: %s +</source> + <translation>ŠŠ·Š¼ŠµŠ½ŠµŠ½: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2540"/> + <source>Modify: %s +</source> + <translation>ŠŠ¾Š“ŠøŃŠøŃŠøŃŠ¾Š²Š°Š½: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2542"/> + <source>Access: %s +</source> + <translation>ŠŠ¾ŃŃŃŠæ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2595"/> + <source>Current run level is %RU32 +</source> + <translation>Š¢ŠµŠŗŃŃŠøŠ¹ ŃŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ %RU32 +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2602"/> + <source>Waiting for run level %RU32 ... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ ŃŃŠ¾Š²Š½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ %RU32 ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2615"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3565"/> + <source>Waiting failed with %Rrc +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ Š·Š°Š²ŠµŃŃŠµŠ½Š¾ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ %Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2621"/> + <source>Run level %RU32 reached +</source> + <translation>Š£ŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ %RU32 Š“Š¾ŃŃŠøŠ³Š½ŃŃ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2630"/> + <source>Run level %RU32 not reached within time +</source> + <translation>Š£ŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ %RU32 Š½Šµ Š“Š¾ŃŃŠøŠ³Š½ŃŃ Š·Š° Š¾ŃŠ²ŠµŠ“ŠµŠ½Š½Š¾Šµ Š²ŃŠµŠ¼Ń +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2716"/> + <source>RTPathAbsCxx failed on '%s': %Rrc</source> + <translation>RTPathAbsCxx Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2745"/> + <source>Updating Guest Additions ... +</source> + <translation>ŠŠ±Š½Š¾Š²Š»ŠµŠ½ŠøŠµ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2761"/> + <source>No Guest Additions source found or specified, aborting +</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½ Šø Š½Šµ ŃŠŗŠ°Š·Š°Š½ ŠøŃŃŠ¾ŃŠ½ŠøŠŗ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”, ŠæŃŠµŃŃŠ²Š°Š½ŠøŠµ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2766"/> + <source>Source "%s" does not exist! +</source> + <translation>ŠŃŃŠ¾ŃŠ½ŠøŠŗ "%s" Š½Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ! +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2777"/> + <source>OS type:</source> + <translation>Š¢ŠøŠæ ŠŠ”:</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2782"/> + <source>Additions run level:</source> + <translation>Š£ŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹:</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2794"/> + <source>Additions version:</source> + <translation>ŠŠµŃŃŠøŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹:</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2802"/> + <source>Using source: %s +</source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·ŃŠµŠ¼ŃŠ¹ ŠøŃŃŠ¾ŃŠ½ŠøŠŗ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2811"/> + <source>Waiting for current Guest Additions inside VM getting ready for updating ... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ Š³Š¾ŃŠ¾Š²Š½Š¾ŃŃŠø ŃŠµŠŗŃŃŠøŃ
ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š²Š½ŃŃŃŠø ŠŠ Š“Š»Ń Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŃ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2832"/> + <source>Guest Additions %lsr%RU64 currently installed, waiting for Guest Additions installer to start ... +</source> + <translation>Š”ŠµŠ¹ŃŠ°Ń ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Ń ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” %lsr%RU64, Š¾Š¶ŠøŠ“Š°Š½ŠøŠµ Š·Š°ŠæŃŃŠŗŠ° ŠøŠ½ŃŃŠ°Š»Š»ŃŃŠ¾ŃŠ° ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2856"/> + <source>Guest Additions update failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾Š±Š½Š¾Š²ŠøŃŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2861"/> + <source>Guest Additions update successful. +</source> + <translation>ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” ŃŃŠæŠµŃŠ½Š¾ Š¾Š±Š½Š¾Š²Š»ŠµŠ½Ń. +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2866"/> + <source>Rebooting guest ... +</source> + <translation>ŠŠµŃŠµŠ·Š°Š³ŃŃŠ·ŠŗŠ° Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2874"/> + <source>Current installed Guest Additions don't support automatic rebooting. Please reboot manually. +</source> + <translation>Š£ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š½ŃŠµ ŃŠµŠ¹ŃŠ°Ń ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŃŃ Š°Š²ŃŠ¾Š¼Š°ŃŠøŃŃŠŗŃŃ ŠæŠµŃŠµŠ·Š°Š³ŃŃŠ·ŠŗŃ. ŠŠ¾Š¶Š°Š»ŃŠ¹ŃŃŠ°, ŠæŠµŃŠµŠ·Š°Š³ŃŃŠ·ŠøŃŠµ Š²ŃŃŃŠ½ŃŃ. +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2886"/> + <source>Waiting for new Guest Additions inside VM getting ready ... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ Š³Š¾ŃŠ¾Š²Š½Š¾ŃŃŠø Š½Š¾Š²ŃŃ
ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” Š²Š½ŃŃŃŠø ŠŠ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2894"/> + <source>Verifying Guest Additions update ... +</source> + <translation>ŠŃŠ¾Š²ŠµŃŠŗŠ° Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2913"/> + <source>Old Guest Additions: %ls%RU64 +</source> + <translation>Š”ŃŠ°ŃŃŠµ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”: %ls%RU64 +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2915"/> + <source>New Guest Additions: %ls%RU64 +</source> + <translation>ŠŠ¾Š²ŃŠµ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”: %ls%RU64 +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2920"/> + <source> +Error updating Guest Additions, please check guest installer log +</source> + <translation> +ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠø ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”, ŠæŠ¾Š¶Š°Š»ŃŠ¹ŃŃŠ°, ŠæŃŠ¾Š²ŠµŃŃŃŠµ Š³Š¾ŃŃŠµŠ²Š¾Š¹ Š¶ŃŃŠ½Š°Š» ŃŃŃŠ°Š½Š¾Š²ŠŗŠø +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2925"/> + <source> +WARNING: Guest Additions were downgraded +</source> + <translation> +ŠŠ ŠŠŠ£ŠŠ ŠŠŠŠŠŠŠ: Š£ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Ń Š±Š¾Š»ŠµŠµ ŃŃŠ°ŃŃŠµ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2932"/> + <source>The guest needs to be restarted in order to make use of the updated Guest Additions. +</source> + <translation>ŠŠ¾ŃŃŠµŠ²ŃŃ ŃŠøŃŃŠµŠ¼Ń Š½Š°Š“Š¾ ŠæŠµŃŠµŠ·Š°Š³ŃŃŠ·ŠøŃŃ Š“Š»Ń ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½ŠøŃ Š½Š¾Š²ŃŃ
ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ”. +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3005"/> + <source>Invalid run level specified. Valid values are: system, userland, desktop</source> + <translation>Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ. ŠŠ¾ŠæŃŃŃŠøŠ¼ŃŠµ Š·Š½Š°ŃŠµŠ½ŠøŃ: system, userland, desktop</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3019"/> + <source>Missing run level to wait for</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŃŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ Š“Š»Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3066"/> + <source>Unknown list: '%s'</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½ŃŠ¹ ŃŠæŠøŃŠ¾Šŗ: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3076"/> + <source>Missing list name</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ¼Ń ŃŠæŠøŃŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3097"/> + <source>Active guest sessions: +</source> + <translation>ŠŠŗŃŠøŠ²Š½ŃŠµ Š³Š¾ŃŃŠµŠ²ŃŠµ ŃŠµŃŃŠøŠø: +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3116"/> + <source> + Session #%-3zu ID=%-3RU32 User=%-16ls Status=[%s] Name=%ls</source> + <translation> + Š”ŠµŃŃŠøŃ #%-3zu ID=%-3RU32 ŠŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»Ń=%-16ls Š”ŃŠ°ŃŃŃ=[%s] ŠŠ¼Ń=%ls</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3139"/> + <source> + Process #%-03zu PID=%-6RU32 Status=[%s] Command=%ls</source> + <translation> + ŠŃŠ¾ŃŠµŃŃ#%-03zu PID=%-6RU32 Š”ŃŠ°ŃŃŃ=[%s] ŠŠ¾Š¼Š°Š½Š“Š°=%ls</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3167"/> + <source> + File #%-03zu ID=%-6RU32 Status=[%s] Name=%ls</source> + <translation> + Š¤Š°Š¹Š» #%-03zu ID=%-6RU32 Š”ŃŠ°ŃŃŃ=[%s] ŠŠ¼Ń=%ls</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3178"/> + <source> + +Total guest sessions: %zu +</source> + <translation> + +ŠŃŠµŠ³Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
ŃŠµŃŃŠøŠ¹: %zu +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3180"/> + <source>Total guest processes: %zu +</source> + <translation>ŠŃŠµŠ³Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
ŠæŃŠ¾ŃŠµŃŃŠ¾Š²: %zu +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3182"/> + <source>Total guest files: %zu +</source> + <translation>ŠŃŠµŠ³Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
ŃŠ°Š¹Š»Š¾Š²: %zu +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3185"/> + <source>No active guest sessions found +</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ Š°ŠŗŃŠøŠ²Š½ŃŃ
Š³Š¾ŃŃŠµŠ²ŃŃ
ŃŠµŃŃŠøŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3251"/> + <source>Invalid PID value: 0</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ PID: 0</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3254"/> + <source>Error parsing PID value: %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š·Š½Š°ŃŠµŠ½ŠøŃ PID: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3264"/> + <source>At least one PID must be specified to kill!</source> + <translation>ŠŃŠ¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ Ń
Š¾ŃŃ Š±Ń Š¾Š“ŠøŠ½ PID, ŠŗŠ¾ŃŠ¾ŃŃŠ¹ Š½Š°Š“Š¾ ŃŠ±ŠøŃŃ!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3268"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3422"/> + <source>No session ID specified!</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ID ŃŠµŃŃŠøŠø!</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3272"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3426"/> + <source>Either session ID or name (pattern) must be specified</source> + <translation>ŠŃŠ¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ Š»ŠøŠ±Š¾ ID ŃŠµŃŃŠøŠø Š»ŠøŠ±Š¾ ŠøŠ¼Ń (ŃŠ°Š±Š»Š¾Š½)</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3335"/> + <source>Terminating process (PID %RU32) (session ID %RU32) ... +</source> + <translation>ŠŠ°Š²ŠµŃŃŠµŠ½ŠøŠµ ŠæŃŠ¾ŃŠµŃŃŠ° (PID %RU32) (ID ŃŠµŃŃŠøŠø %RU32) ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3343"/> + <source>No matching process(es) for session ID %RU32 found +</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ ŃŠ¾Š¾ŃŠ²ŠµŃŃŃŠ²ŃŃŃŠøŃ
ŠæŃŠ¾ŃŠµŃŃŠ¾Š² Š“Š»Ń ID ŃŠµŃŃŠøŠø %RU32 +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3355"/> + <source>No matching session(s) found +</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ ŃŠ¾Š¾ŃŠ²ŠµŃŃŃŠ²ŃŃŃŠøŃ
ŃŠµŃŃŠøŠ¹ +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="3358"/> + <source>%RU32 process(es) terminated +</source> + <translation> + <numerusform>ŠŠ°Š²ŠµŃŃŠµŠ½ %RU32 ŠæŃŠ¾ŃŠµŃŃ +</numerusform> + <numerusform>ŠŠ°Š²ŠµŃŃŠµŠ½Š¾ %RU32 ŠæŃŠ¾ŃŠµŃŃŠ° +</numerusform> + <numerusform>ŠŠ°Š²ŠµŃŃŠµŠ½Š¾ %RU32 ŠæŃŠ¾ŃŠµŃŃŠ¾Š² +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3464"/> + <source>Closing guest session ID=#%RU32 "%s" ... +</source> + <translation>ŠŠ°ŠŗŃŃŃŠøŠµ Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠµŃŃŠøŠø ID=#%RU32 "%s"... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3468"/> + <source>Guest session successfully closed +</source> + <translation>ŠŠ¾ŃŃŠµŠ²Š°Ń ŃŠµŃŃŠøŃ ŃŃŠæŠµŃŠ½Š¾ Š·Š°ŠŗŃŃŃŠ° +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3476"/> + <source>No guest session(s) found +</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
ŃŠµŃŃŠøŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3554"/> + <source>Waiting for events ... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ ŃŠ¾Š±ŃŃŠøŠ¹... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3709"/> + <source>Unknown sub-command: '%s'</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3718"/> + <source>Missing sub-command</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3720"/> + <source>Missing VM name and sub-command</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ¼Ń ŠŠ Šø ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°</translation> + </message> +</context> +<context> + <name>GuestCtrlLsnr</name> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="106"/> + <source>File ID=%RU32 "%s" changed status to [%s] +</source> + <translation>Š¤Š°Š¹Š» Ń ID=%RU32 "%s" ŠøŠ·Š¼ŠµŠ½ŠøŠ» ŃŃŠ°ŃŃŃ Š½Š° [%s] +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="162"/> + <source>Process PID=%RU32 "%s" changed status to [%s] +</source> + <translation>ŠŃŠ¾ŃŠµŃŃ PID=%RU32 "%s" ŠøŠ·Š¼ŠµŠ½ŠøŠ» ŃŃŠ°ŃŃŃ Š½Š° [%s] +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="254"/> + <source>File "%s" %s +</source> + <translation>Š¤Š°Š¹Š» "%s" %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="256"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="320"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="461"/> + <source>registered</source> + <translation>ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŃ ŃŠ“ŠµŠ»Š°Š½Š°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="256"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="320"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="461"/> + <source>unregistered</source> + <translation>ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŃ Š¾ŃŠ¼ŠµŠ½ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="260"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="324"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="465"/> + <source>Registering ... +</source> + <translation>Š ŠµŠ³ŠøŃŃŃŠ°ŃŠøŃ... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="283"/> + <source>Unregistering file ... +</source> + <translation>ŠŃŠ¼ŠµŠ½Š° ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŠø ŃŠ°Š¹Š»Š°... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="318"/> + <source>Process "%s" %s +</source> + <translation>ŠŃŠ¾ŃŠµŃŃ "%s" %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="347"/> + <source>Unregistering process ... +</source> + <translation>ŠŃŠ¼ŠµŠ½Š° ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŠø ŠæŃŠ¾ŃŠµŃŃŠ°... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="384"/> + <source>Session ID=%RU32 "%s" changed status to [%s] +</source> + <translation>Š”ŠµŃŃŠøŃ ID=%RU32 "%s" ŠøŠ·Š¼ŠµŠ½ŠøŠ»Š° ŃŃŠ°ŃŃŃ Š½Š° [%s] +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="459"/> + <source>Session ID=%RU32 "%s" %s +</source> + <translation>Š”ŠµŃŃŠøŃ ID=%RU32 "%s" %s +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="490"/> + <source>Unregistering ... +</source> + <translation>ŠŃŠ¼ŠµŠ½Š° ŃŠµŠ³ŠøŃŃŃŠ°ŃŠøŠø... +</translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="552"/> + <source>Reached run level %RU32 +</source> + <translation>ŠŠ¾ŃŃŠøŠ³Š½ŃŃ ŃŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ %RU32 +</translation> + </message> +</context> +<context> + <name>GuestProp</name> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="64"/> + <location filename="../VBoxManageGuestProp.cpp" line="125"/> + <location filename="../VBoxManageGuestProp.cpp" line="171"/> + <location filename="../VBoxManageGuestProp.cpp" line="215"/> + <location filename="../VBoxManageGuestProp.cpp" line="304"/> + <location filename="../VBoxManageGuestProp.cpp" line="407"/> + <location filename="../VBoxManageGuestProp.cpp" line="422"/> + <source>Incorrect parameters</source> + <translation>ŠŠµŠŗŠ¾ŃŃŠµŠŗŃŠ½ŃŠµ ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="84"/> + <source>No value set! +</source> + <translation>ŠŠµ Š·Š°Š“Š°Š½Š¾ ŠŗŠ°ŠŗŠ¾Šµ-Š»ŠøŠ±Š¾ Š·Š½Š°ŃŠµŠ½ŠøŠµ! +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="86"/> + <source>Value: %ls +</source> + <translation>ŠŠ½Š°ŃŠµŠ½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="89"/> + <source>Timestamp: %lld +</source> + <translation>ŠŃŠµŠ¼Ń: %lld +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="90"/> + <source>Flags: %ls +</source> + <translation>Š¤Š»Š°Š³Šø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="251"/> + <source>No properties found. +</source> + <translation>Š”Š²Š¾Š¹ŃŃŠ²Š° Š½Šµ Š½Š°Š¹Š“ŠµŠ½Ń. +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="253"/> + <source>Name: %ls, value: %ls, timestamp: %lld, flags: %ls +</source> + <translation>ŠŠ¼Ń: %ls, Š·Š½Š°ŃŠµŠ½ŠøŠµ: %ls, Š²ŃŠµŠ¼Ń: %lld, ŃŠ»Š°Š³Šø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="362"/> + <source>Property %ls was deleted +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="364"/> + <source>Name: %ls, value: %ls, flags: %ls +</source> + <translation>ŠŠ¼Ń: %ls, Š·Š½Š°ŃŠµŠ½ŠøŠµ: %ls, ŃŠ»Š°Š³Šø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="381"/> + <source>Time out or interruption while waiting for a notification.</source> + <translation>ŠŃŠµŠ²ŃŃŠµŠ½Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ ŠøŠ»Šø ŠæŃŠµŃŃŠ²Š°Š½ŠøŠµ Š²Š¾ Š²ŃŠµŠ¼Ń Š¾Š¶ŠøŠ“Š°Š½ŠøŃ Š¾ŠæŠ¾Š²ŠµŃŠµŠ½ŠøŃ.</translation> + </message> +</context> +<context> + <name>Help</name> + <message> + <location filename="../VBoxManageHelp.cpp" line="139"/> + <source>Usage - %s%s: +</source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½ŠøŠµ - %s%s: +</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="142"/> + <source>Usage: +</source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½ŠøŠµ: +</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="231"/> + <source>No subcommand specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š° ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="257"/> + <source>Unknown subcommand: %s</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°: %s</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="290"/> + <source>Too many parameters</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="397"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="401"/> + <source>Invalid option -%c</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń Š¾ŠæŃŠøŃ -%c</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="403"/> + <source>Invalid option case %i</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²Š°ŃŠøŠ°Š½Ń Š¾ŠæŃŠøŠø %i</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="406"/> + <source>Unknown option: %s</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="408"/> + <source>Invalid argument format: %s</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠ¾ŃŠ¼Š°Ń Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ°: %s</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="432"/> + <source>Missing the %u%s value for option %s</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ %u%s Š·Š½Š°ŃŠµŠ½ŠøŠµ Š“Š»Ń Š¾ŠæŃŠøŠø %s</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="434"/> + <source>st</source> + <translation>Š¾Šµ</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="435"/> + <source>nd</source> + <translation>Š¾Šµ</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="436"/> + <source>rd</source> + <translation>ŃŠµ</translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="437"/> + <source>th</source> + <translation>Š¾Šµ</translation> + </message> + <message> + <source>Usage: + +</source> + <translation type="vanished">ŠŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½ŠøŠµ: + +</translation> + </message> + <message> + <source> +Syntax error: %N +</source> + <translation type="vanished"> +Š”ŠøŠ½ŃŠ°ŠŗŃŠøŃŠµŃŠŗŠ°Ń Š¾ŃŠøŠ±ŠŗŠ°: %N +</translation> + </message> +</context> +<context> + <name>HostOnly</name> + <message> + <location filename="../VBoxManageHostonly.cpp" line="95"/> + <source>Failed to create the host-only adapter</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠ¹ Š°Š“Š°ŠæŃŠµŃ Ń
Š¾ŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="104"/> + <source>Interface '%ls' was successfully created +</source> + <translation>ŠŠ½ŃŠµŃŃŠµŠ¹Ń '%ls' ŃŃŠæŠµŃŠ½Š¾ ŃŠ¾Š·Š“Š°Š½ +</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="123"/> + <location filename="../VBoxManageHostonly.cpp" line="214"/> + <source>Only one interface name can be specified</source> + <translation>ŠŠ¾Š¶ŠµŃ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½Š¾ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“Š½Š¾ ŠøŠ¼Ń ŠøŠ½ŃŠµŃŃŠµŠ¹ŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="131"/> + <source>No interface name was specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠøŠ½ŃŠµŃŃŠµŠ¹ŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="149"/> + <source>Failed to remove the host-only adapter</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠ¹ Š°Š“Š°ŠæŃŠµŃ Ń
Š¾ŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="193"/> + <source>The --ip option is specified more than once</source> + <translation>ŠŠæŃŠøŃ --ip ŃŠŗŠ°Š·Š°Š½Š° Š±Š¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°Š·Š°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="198"/> + <source>The --netmask option is specified more than once</source> + <translation>ŠŠæŃŠøŃ --netmask ŃŠŗŠ°Š·Š°Š½Š° Š±Š¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°Š·Š°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="203"/> + <source>The --ipv6 option is specified more than once</source> + <translation>ŠŠæŃŠøŃ --ipv6 ŃŠŗŠ°Š·Š°Š½Š° Š±Š¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°Š·Š°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="208"/> + <source>The --netmasklengthv6 option is specified more than once</source> + <translation>ŠŠæŃŠøŃ --netmasklengthv6 ŃŠŗŠ°Š·Š°Š½Š° Š±Š¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°Š·Š°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="224"/> + <source>You can not use --dhcp with static ip configuration parameters: --ip, --netmask, --ipv6 and --netmasklengthv6.</source> + <translation>ŠŠµŠ»ŃŠ·Ń ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŃ --dhcp Ń ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ°Š¼Šø ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø ŃŃŠ°ŃŠøŃŠµŃŠŗŠ¾Š³Š¾ ip: --ip, --netmask, --ipv6 and --netmasklengthv6.</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="226"/> + <source>You can not use ipv4 configuration (--ip and --netmask) with ipv6 (--ipv6 and --netmasklengthv6) simultaneously.</source> + <translation>ŠŠµŠ»ŃŠ·Ń ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ ipv4 (--ip Šø --netmask) Ń ipv6 (--ipv6 Šø --netmasklengthv6) Š¾Š“Š½Š¾Š²ŃŠµŠ¼ŠµŠ½Š½Š¾.</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="234"/> + <source>Could not find interface '%s'</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠøŠ½ŃŠµŃŃŠµŠ¹Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="250"/> + <source>IPv6 setting is not supported for this adapter</source> + <translation>ŠŠ°Š¹ŃŃŃŠ¾Š¹ŠŗŠø IPv6 Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŃŃŃŃ Š“Š»Ń ŃŃŠ¾Š³Š¾ Š°Š“Š°ŠæŃŠµŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="259"/> + <source>Neither -dhcp nor -ip nor -ipv6 was specfified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Ń Š½Šø -dhcp Š½Šø -ip Š½Šø -ipv6</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="268"/> + <location filename="../VBoxManageHostonly.cpp" line="514"/> + <source>No sub-command specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š° ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="289"/> + <location filename="../VBoxManageHostonly.cpp" line="533"/> + <source>Unknown sub-command '%s'</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="410"/> + <source>The --name parameter must be specified</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ --name Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="412"/> + <source>The --netmask parameter must be specified</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ --netmask Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="414"/> + <source>The --lower-ip parameter must be specified</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ --lower-ip Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="416"/> + <source>The --upper-ip parameter must be specified</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ --upper-ip Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="447"/> + <location filename="../VBoxManageHostonly.cpp" line="503"/> + <source>Either --name or --id parameter must be specified</source> + <translation>ŠŠµŠ¾Š±Ń
Š¾Š“ŠøŠ¼Š¾ ŃŠŗŠ°Š·Š°ŃŃ Š»ŠøŠ±Š¾ --name Š»ŠøŠ±Š¾ --id</translation> + </message> +</context> +<context> + <name>Info</name> + <message> + <location filename="../VBoxManageInfo.cpp" line="284"/> + <source> %sName: %ls (UUID: %s)%s +</source> + <translation> %sŠŠ¼Ń: %ls (UUID: %s)%s +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="292"/> + <source> %sDescription: +%ls +</source> + <translation> %sŠŠæŠøŃŠ°Š½ŠøŠµ: +%ls +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="341"/> + <source>powered off</source> + <translation>Š²ŃŠŗŠ»ŃŃŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="343"/> + <source>saved</source> + <translation>ŃŠ¾Ń
ŃŠ°Š½ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="345"/> + <source>teleported</source> + <translation>ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="347"/> + <source>aborted</source> + <translation>ŠæŃŠµŃŠ²Š°Š½Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="349"/> + <source>aborted-saved</source> + <translation>ŠæŃŠµŃŠ²Š°Š½Š°-ŃŠ¾Ń
ŃŠ°Š½ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="351"/> + <source>running</source> + <translation>ŃŠ°Š±Š¾ŃŠ°ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="353"/> + <location filename="../VBoxManageInfo.cpp" line="399"/> + <source>paused</source> + <translation>ŠæŃŠøŠ¾ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="355"/> + <source>guru meditation</source> + <translation>Š³ŃŃŃ Š¼ŠµŠ“ŠøŃŠ°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="357"/> + <source>teleporting</source> + <translation>ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="359"/> + <source>live snapshotting</source> + <translation>ŃŠ¾Š·Š“Š°Š½ŠøŠµ Š¶ŠøŠ²Š¾Š³Š¾ ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="361"/> + <source>starting</source> + <translation>Š·Š°ŠæŃŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="363"/> + <source>stopping</source> + <translation>Š¾ŃŃŠ°Š½Š¾Š²ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="365"/> + <source>saving</source> + <translation>ŃŠ¾Ń
ŃŠ°Š½ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="367"/> + <source>restoring</source> + <translation>Š²Š¾ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="369"/> + <source>teleporting paused vm</source> + <translation>ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½ŠøŠµ ŠæŃŠøŠ¾ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š½Š¾Š¹ Š²Š¼</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="371"/> + <source>teleporting (incoming)</source> + <translation>ŠæŠ¾ŃŃŠøŃŠ¾Š²Š°Š½ŠøŠµ (ŠøŠ·Š²Š½Šµ)</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="373"/> + <source>deleting snapshot live</source> + <translation>ŃŠ“Š°Š»ŠµŠ½ŠøŠµ Š¶ŠøŠ²Š¾Š³Š¾ ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="375"/> + <source>deleting snapshot live paused</source> + <translation>ŃŠ“Š°Š»ŠµŠ½ŠøŠµ Š¶ŠøŠ²Š¾Š³Š¾ ŃŠ½ŠøŠ¼ŠŗŠ° ŠæŃŠøŠ¾ŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="377"/> + <source>online snapshotting</source> + <translation>ŃŠ¾Š·Š“Š°Š½ŠøŠµ Š¾Š½Š»Š°Š¹Š½ ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="379"/> + <source>restoring snapshot</source> + <translation>Š²Š¾ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½ŠøŠµ ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="381"/> + <source>deleting snapshot</source> + <translation>ŃŠ“Š°Š»ŠµŠ½ŠøŠµ ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="383"/> + <source>setting up</source> + <translation>Š½Š°ŃŃŃŠ¾Š¹ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="385"/> + <source>offline snapshotting</source> + <translation>ŃŠ¾Š·Š“Š°Š½ŠøŠµ Š¾ŃŠ»Š°Š¹Š½ ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="389"/> + <location filename="../VBoxManageInfo.cpp" line="416"/> + <location filename="../VBoxManageInfo.cpp" line="446"/> + <location filename="../VBoxManageInfo.cpp" line="699"/> + <location filename="../VBoxManageInfo.cpp" line="1186"/> + <location filename="../VBoxManageInfo.cpp" line="1206"/> + <location filename="../VBoxManageInfo.cpp" line="1806"/> + <location filename="../VBoxManageInfo.cpp" line="1860"/> + <location filename="../VBoxManageInfo.cpp" line="2412"/> + <source>unknown</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="397"/> + <location filename="../VBoxManageInfo.cpp" line="2738"/> + <location filename="../VBoxManageInfo.cpp" line="2828"/> + <location filename="../VBoxManageInfo.cpp" line="2830"/> + <source>not active</source> + <translation>Š½ŠµŠ°ŠŗŃŠøŠ²Š½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="401"/> + <source>pre-initializing</source> + <translation>ŠæŃŠµŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·Š°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="403"/> + <source>initializing</source> + <translation>ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·Š°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="405"/> + <source>active/running</source> + <translation>Š°ŠŗŃŠøŠ²Š½Š¾/ŃŠ°Š±Š¾ŃŠ°ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="407"/> + <source>terminating</source> + <translation>Š·Š°Š²ŠµŃŃŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="409"/> + <source>terminated</source> + <translation>Š·Š°Š²ŠµŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="411"/> + <source>failed</source> + <translation>Š¾ŃŠŗŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="692"/> + <location filename="../VBoxManageInfo.cpp" line="1404"/> + <location filename="../VBoxManageInfo.cpp" line="2139"/> + <source>Null</source> + <translation>ŠŃŃŃŠ¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="693"/> + <source>Disk</source> + <translation>ŠŠøŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="694"/> + <location filename="../VBoxManageInfo.cpp" line="1295"/> + <source>Network</source> + <translation>Š”ŠµŃŃ</translation> + </message> + <message> + <source>Name: '%ls', Type: %s, Limit: none (disabled) +</source> + <translation type="vanished">ŠŠ¼Ń: '%ls', Š¢ŠøŠæ: %s, ŠŠøŠ¼ŠøŃ: Š½ŠµŃ(Š¾ŃŠŗŠ»ŃŃŠµŠ½Š¾) +</translation> + </message> + <message> + <source>Name: '%ls', Type: %s, Limit: %lld %sbits/sec (%lld %sbytes/sec) +</source> + <translation type="vanished">ŠŠ¼Ń: '%ls', Š¢ŠøŠæ: %s, ŠŠøŠ¼ŠøŃ: %lld %sŠ±ŠøŃ/ŃŠµŠŗ (%lld %sŠ±Š°Š¹Ń/ŃŠµŠŗ) +</translation> + </message> + <message> + <source>Name: '%ls', Type: %s, Limit: %lld %sbytes/sec +</source> + <translation type="vanished">ŠŠ¼Ń: '%ls', Š¢ŠøŠæ: %s, ŠŠøŠ¼ŠøŃ: %lld %sŠ±Š°Š¹Ń/ŃŠµŠŗ +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="813"/> + <source>Name: '%ls', Host path: '%ls' (%s), %s%s</source> + <translation>ŠŠ¼Ń: '%ls', ŠŃŃŃ Ń
Š¾ŃŃŠ°: '%ls' (%s), %s%s</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="814"/> + <source>writable</source> + <translation>Š·Š°ŠæŠøŃŃŠ²Š°ŠµŠ¼ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="814"/> + <source>readonly</source> + <translation>ŃŠ¾Š»ŃŠŗŠ¾ Š“Š»Ń ŃŃŠµŠ½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="815"/> + <source>, auto-mount</source> + <translation>, Š°Š²ŃŠ¾Š¼Š¾Š½ŃŠøŃŠ¾Š²Š°Š½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="817"/> + <source>, mount-point: '%ls' +</source> + <translation>, ŃŠ¾ŃŠŗŠ° ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŃ: '%ls' +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="995"/> + <location filename="../VBoxManageInfo.cpp" line="1027"/> + <location filename="../VBoxManageInfo.cpp" line="1914"/> + <location filename="../VBoxManageInfo.cpp" line="1950"/> + <source>None</source> + <translation>ŠŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1000"/> + <source>Automatic</source> + <translation>ŠŠ²ŃŠ¾Š¼Š°ŃŠøŃŠµŃŠŗŠø</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1015"/> + <location filename="../VBoxManageInfo.cpp" line="1057"/> + <location filename="../VBoxManageInfo.cpp" line="1428"/> + <location filename="../VBoxManageInfo.cpp" line="1908"/> + <location filename="../VBoxManageInfo.cpp" line="1945"/> + <location filename="../VBoxManageInfo.cpp" line="2124"/> + <location filename="../VBoxManageInfo.cpp" line="2125"/> + <location filename="../VBoxManageInfo.cpp" line="2126"/> + <location filename="../VBoxManageInfo.cpp" line="2269"/> + <location filename="../VBoxManageInfo.cpp" line="2298"/> + <source>Unknown</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1032"/> + <source>Default</source> + <translation>ŠŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1037"/> + <source>Legacy</source> + <translation>Š£ŃŃŠ°ŃŠµŠ²ŃŠøŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1042"/> + <source>Minimal</source> + <translation>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="85"/> + <location filename="../VBoxManageInfo.cpp" line="108"/> + <location filename="../VBoxManageInfo.cpp" line="131"/> + <location filename="../VBoxManageInfo.cpp" line="2240"/> + <location filename="../VBoxManageInfo.cpp" line="2349"/> + <location filename="../VBoxManageInfo.cpp" line="2882"/> + <location filename="../VBoxManageInfo.cpp" line="2884"/> + <source>enabled</source> + <translation>Š²ŠŗŠ»ŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="85"/> + <location filename="../VBoxManageInfo.cpp" line="108"/> + <location filename="../VBoxManageInfo.cpp" line="131"/> + <location filename="../VBoxManageInfo.cpp" line="1263"/> + <location filename="../VBoxManageInfo.cpp" line="1317"/> + <location filename="../VBoxManageInfo.cpp" line="2240"/> + <location filename="../VBoxManageInfo.cpp" line="2350"/> + <location filename="../VBoxManageInfo.cpp" line="2882"/> + <location filename="../VBoxManageInfo.cpp" line="2884"/> + <source>disabled</source> + <translation>Š²ŃŠŗŠ»ŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="290"/> + <source> %sDescription: %ls +</source> + <translation> %sŠŠæŠøŃŠ°Š½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="862"/> + <location filename="../VBoxManageInfo.cpp" line="1542"/> + <location filename="../VBoxManageInfo.cpp" line="2572"/> + <location filename="../VBoxManageInfo.cpp" line="2985"/> + <source><none></source> + <translation><Š½ŠµŃ></translation> + </message> + <message> + <source> Port %u, Unit %u: UUID: %ls%s%s%s + Location: "%ls" +</source> + <translation type="vanished"> ŠŠ¾ŃŃ %u, Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š¾ %u: UUID: %ls%s%s%s + Š Š°ŃŠæŠ¾Š»Š¾Š¶ŠµŠ½ŠøŠµ: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="922"/> + <source>, passthrough enabled</source> + <translation>, ŠæŃŃŠ¼Š¾Š¹ Š“Š¾ŃŃŃŠæ Š²ŠŗŠ»ŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="923"/> + <location filename="../VBoxManageInfo.cpp" line="966"/> + <source>, temp eject</source> + <translation>, Š²ŃŠµŠ¼ŠµŠ½Š½Š¾ ŠøŠ·Š²Š»ŠµŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="924"/> + <location filename="../VBoxManageInfo.cpp" line="967"/> + <source>, ejected</source> + <translation>, ŠøŠ·Š²Š»ŠµŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="925"/> + <source>, hot-pluggable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="926"/> + <source>, non-rotational (SSD)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="927"/> + <source>, discards unused blocks</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="965"/> + <source> Port %u, Unit %u: Empty%s%s +</source> + <translation> ŠŠ¾ŃŃ %u, Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š¾ %u: ŠŃŃŃŠ¾Š¹%s%s +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="979"/> + <source> Port %u, Unit %u: GetMedium failed: %Rhrc +</source> + <translation> ŠŠ¾ŃŃ %u, Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š¾ %u: GetMedium Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1106"/> + <source>"<inaccessible>" {%s} +</source> + <translation>"<Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š¾>" {%s} +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1112"/> + <source>Name: <inaccessible!> +</source> + <translation>ŠŠ¼Ń: <Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š¾!> +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1121"/> + <source>Config file: %ls +</source> + <translation>Š¤Š°Š¹Š» ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1124"/> + <source>Access error details: +</source> + <translation>ŠŠµŃŠ°Š»Šø Š¾ŃŠøŠ±ŠŗŠø Š“Š¾ŃŃŃŠæŠ°: +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1144"/> + <source>Name:</source> + <translation>ŠŠ¼Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1145"/> + <source>Groups:</source> + <translation>ŠŃŃŠæŠæŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1151"/> + <location filename="../VBoxManageInfo.cpp" line="1153"/> + <source>Guest OS:</source> + <translation>ŠŠ¾ŃŃŠµŠ²Š°Ń ŠŠ”:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1155"/> + <source>Config file:</source> + <translation>Š¤Š°Š¹Š» ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1156"/> + <source>Snapshot folder:</source> + <translation>ŠŠ°ŠæŠŗŠ° ŃŠ½ŠøŠ¼ŠŗŠ¾Š²:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1157"/> + <source>Log folder:</source> + <translation>ŠŠ°ŠæŠŗŠ° Š¶ŃŃŠ½Š°Š»Š¾Š²:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1158"/> + <source>Hardware UUID:</source> + <translation>ŠŠæŠæŠ°ŃŠ°ŃŠ½ŃŠ¹ UUID:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1159"/> + <source>Memory size:</source> + <translation>Š Š°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1160"/> + <source>Page Fusion:</source> + <translation>Page Fusion:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1163"/> + <source>VRAM size:</source> + <translation>Š Š°Š·Š¼ŠµŃ VRAM:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1164"/> + <source>CPU exec cap:</source> + <translation>ŠŃŠ¾ŃŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ Š¦ŠŠ£:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1165"/> + <source>HPET:</source> + <translation>HPET:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1166"/> + <source>CPUProfile:</source> + <translation>ŠŃŠ¾ŃŠøŠ»Ń Š¦ŠŠ£:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1177"/> + <source>invalid</source> + <translation>Š½ŠµŠ“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1189"/> + <source>Chipset:</source> + <translation>Š§ŠøŠæŃŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1209"/> + <source>Firmware:</source> + <translation>ŠŃŠ¾ŃŠøŠ²ŠŗŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1211"/> + <source>Number of CPUs:</source> + <translation>Š§ŠøŃŠ»Š¾ Š¦ŠŠ£:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1213"/> + <source>Long Mode:</source> + <translation>ŠŠ»ŠøŠ½Š½ŃŠ¹ ŃŠµŠ¶ŠøŠ¼:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1214"/> + <source>Triple Fault Reset:</source> + <translation>Š”Š±ŃŠ¾Ń Š¢ŃŠ¾Š¹Š½Š¾Š³Š¾ ŠŃŠŗŠ°Š·Š°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1217"/> + <source>Nested VT-x/AMD-V:</source> + <translation>ŠŠ»Š¾Š¶ŠµŠ½Š½ŃŠµ Nested VT-x/AMD-V:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1218"/> + <source>CPUID Portability Level:</source> + <translation>Š£ŃŠ¾Š²ŠµŠ½Ń ŠŠ¾ŃŃŠ°ŃŠøŠ²Š½Š¾ŃŃŠø CPUID:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1221"/> + <source>CPUID overrides:</source> + <translation>CPUID Š·Š°Š¼ŠµŠ½Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1234"/> + <source>Leaf no. EAX EBX ECX EDX +</source> + <translation>ŠŠøŃŃ no. EAX EBX ECX EDX +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1246"/> + <source>None +</source> + <translation>ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1269"/> + <source>menu only</source> + <translation>ŃŠ¾Š»ŃŠŗŠ¾ Š¼ŠµŠ½Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1275"/> + <source>message and menu</source> + <translation>ŃŠ¾Š¾Š±ŃŠµŠ½ŠøŃ Šø Š¼ŠµŠ½Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1277"/> + <source>Boot menu mode:</source> + <translation>Š ŠµŠ¶ŠøŠ¼ Š·Š°Š³ŃŃŠ·Š¾ŃŠ½Š¾Š³Š¾ Š¼ŠµŠ½Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1289"/> + <source>Floppy</source> + <translation>Š¤Š»Š¾ŠæŠæŠø</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1293"/> + <source>HardDisk</source> + <translation>ŠŠµŃŃŠŗŠøŠ¹ ŠŠøŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1299"/> + <source>Shared Folder</source> + <translation>ŠŠ±ŃŠ°Ń ŠæŠ°ŠæŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1301"/> + <source>Not Assigned</source> + <translation>ŠŠµ Š½Š°Š·Š½Š°ŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1302"/> + <source>Boot Device %u:</source> + <translation>ŠŠ°Š³ŃŃŠ·Š¾ŃŠ½Š¾Šµ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾ %u:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1333"/> + <source>BIOS APIC mode:</source> + <translation>Š ŠµŠ¶ŠøŠ¼ BIOS APIC:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1335"/> + <source>Time offset:</source> + <translation>Š§Š°ŃŠ¾Š²Š¾Š¹ ŠæŠ¾ŃŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1335"/> + <source>ms</source> + <translation>Š¼Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1339"/> + <source>BIOS NVRAM File:</source> + <translation>Š¤Š°Š¹Š» BIOS NVRAM:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1340"/> + <source>RTC:</source> + <translation>RTC:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1340"/> + <source>local time</source> + <translation>Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Šµ Š²ŃŠµŠ¼Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1341"/> + <source>Hardware Virtualization:</source> + <translation>ŠŠæŠæŠ°ŃŠ°ŃŠ½Š°Ń ŠŠøŃŃŃŠ°Š»ŠøŠ·Š°ŃŠøŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1342"/> + <source>Nested Paging:</source> + <translation>ŠŠ»Š¾Š¶ŠµŠ½Š½ŃŠµ ŃŃŃŠ°Š½ŠøŃŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1343"/> + <source>Large Pages:</source> + <translation>ŠŠ¾Š»ŃŃŠøŠµ Š”ŃŃŠ°Š½ŠøŃŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1345"/> + <source>VT-x Unrestricted Exec.:</source> + <translation>VT-x ŠŠµŠ¾Š³ŃŠ°Š½ŠøŃŠµŠ½Š½Š¾Šµ Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1346"/> + <source>AMD-V Virt. Vmsave/Vmload:</source> + <translation>AMD-V Virt. Vmsave/Vmload:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1358"/> + <source>Paravirt. Provider:</source> + <translation>ŠŠ°ŃŠ°Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠ¹ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1363"/> + <source>Effective Paravirt. Prov.:</source> + <translation>ŠŃŃŠµŠŗŃŠøŠ²Š½ŃŠ¹ ŠŠ°ŃŠ°Š²ŠøŃŃŃŠ°Š»ŃŠ½ŃŠ¹ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1368"/> + <source>Paravirt. Debug:</source> + <translation>ŠŠ°ŃŠ°Š²ŠøŃŃŃŠ°Š»ŃŠ½Š°Ń Š¾ŃŠ»Š°Š“ŠŗŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1391"/> + <source>%-28s %s (since %s) +</source> + <translation>%-28s %s (Ń %s) +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1391"/> + <source>State:</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1435"/> + <source>Graphics Controller:</source> + <translation>ŠŃŠ°ŃŠøŃŠµŃŠŗŠøŠ¹ ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1438"/> + <source>Monitor count:</source> + <translation>Š§ŠøŃŠ»Š¾ Š¼Š¾Š½ŠøŃŠ¾ŃŠ¾Š²:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1439"/> + <source>3D Acceleration:</source> + <translation>3D Š£ŃŠŗŠ¾ŃŠµŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1441"/> + <source>2D Video Acceleration:</source> + <translation>2D ŠŠøŠ“ŠµŠ¾ Š£ŃŠŗŠ¾ŃŠµŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1443"/> + <source>Teleporter Enabled:</source> + <translation>Š¢ŠµŠ»ŠµŠæŠ¾ŃŃŠµŃ Š²ŠŗŠ»ŃŃŠµŠ½:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1444"/> + <source>Teleporter Port:</source> + <translation>ŠŠ¾ŃŃ ŃŠµŠ»ŠµŠæŠ¾ŃŃŠµŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1445"/> + <source>Teleporter Address:</source> + <translation>ŠŠ“ŃŠµŃ ŃŠµŠ»ŠµŠæŠ¾ŃŃŠµŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1446"/> + <source>Teleporter Password:</source> + <translation>ŠŠ°ŃŠ¾Š»Ń ŃŠµŠ»ŠµŠæŠ¾ŃŃŠµŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1447"/> + <source>Tracing Enabled:</source> + <translation>Š¢ŃŠ°ŃŃŠøŃŠ¾Š²ŠŗŠ° Š²ŠŗŠ»ŃŃŠµŠ½Š°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1448"/> + <source>Allow Tracing to Access VM:</source> + <translation>Š Š°Š·ŃŠµŃŠøŃŃ ŃŃŠ°ŃŃŠøŃŠ¾Š²ŠŗŠµ Š“Š¾ŃŃŃŠæ Šŗ ŠŠ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1449"/> + <source>Tracing Configuration:</source> + <translation>ŠŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ ŃŃŠ°ŃŃŠøŃŠ¾Š²ŠŗŠø:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1450"/> + <source>Autostart Enabled:</source> + <translation>ŠŠ²ŃŠ¾ŃŃŠ°ŃŃ Š²ŠŗŠ»ŃŃŠµŠ½:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1451"/> + <source>Autostart Delay:</source> + <translation>ŠŠ°Š“ŠµŃŠ¶ŠŗŠ° Š°Š²ŃŠ¾ŃŃŠ°ŃŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1452"/> + <source>Default Frontend:</source> + <translation>Š¤ŃŠ¾Š½ŃŃŠ½Š“ ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1463"/> + <source>flat</source> + <translation>ŃŠ°Š²Š½Š¾Š¼ŠµŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1469"/> + <source>low</source> + <translation>Š½ŠøŠ·ŠŗŠøŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1475"/> + <source>normal</source> + <translation>Š½Š¾ŃŠ¼Š°Š»ŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1481"/> + <source>high</source> + <translation>Š²ŃŃŠ¾ŠŗŠøŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1487"/> + <source>default</source> + <translation>ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1490"/> + <source>VM process priority:</source> + <translation>ŠŃŠøŠ¾ŃŠøŃŠµŃ ŠæŃŠ¾ŃŠµŃŃŠ° ŠŠ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2881"/> + <source>VMMDev Testing</source> + <translation>Š¢ŠµŃŃŠøŃŠ¾Š²Š°Š½ŠøŠµ VMMDev</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2882"/> + <location filename="../VBoxManageInfo.cpp" line="2884"/> + <source>misconfigured</source> + <translation>Š½ŠµŠæŃŠ°Š²ŠøŠ»ŃŠ½Š¾ Š½Š°ŃŃŃŠ¾ŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2907"/> + <source>* Snapshots: +</source> + <translation>* Š”Š½ŠøŠ¼ŠŗŠø: +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2916"/> + <source>* Guest: +</source> + <translation>* ŠŠ¾ŃŃŠµŠ²Š°Ń ŃŠøŃŃŠµŠ¼Š°: +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2953"/> + <location filename="../VBoxManageInfo.cpp" line="2985"/> + <source>Guest Facilities:</source> + <translation>Š”ŃŠµŠ“ŃŃŠ²Š° Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1890"/> + <location filename="../VBoxManageInfo.cpp" line="1891"/> + <location filename="../VBoxManageInfo.cpp" line="2452"/> + <location filename="../VBoxManageInfo.cpp" line="2453"/> + <source>on</source> + <translation>Š²ŠŗŠ»</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1890"/> + <location filename="../VBoxManageInfo.cpp" line="1891"/> + <location filename="../VBoxManageInfo.cpp" line="2452"/> + <location filename="../VBoxManageInfo.cpp" line="2453"/> + <source>off</source> + <translation>Š²ŃŠŗŠ»</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1561"/> + <source>NIC %u:</source> + <translation>NIC %u:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="732"/> + <source>#%zu: Name: '%ls', Type: %s, Limit: none (disabled) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="780"/> + <source>#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s (%RI64 %s) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="784"/> + <source>#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="920"/> + <source> Port %u, Unit %u: UUID: %ls%s%s%s%s%s%s + Location: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1570"/> + <location filename="../VBoxManageInfo.cpp" line="1992"/> + <location filename="../VBoxManageInfo.cpp" line="2098"/> + <location filename="../VBoxManageInfo.cpp" line="2459"/> + <location filename="../VBoxManageInfo.cpp" line="2491"/> + <source>%-28s disabled +</source> + <translation>%-28s Š¾ŃŠŗŠ»ŃŃŠµŠ½ +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1587"/> + <location filename="../VBoxManageInfo.cpp" line="1892"/> + <location filename="../VBoxManageInfo.cpp" line="1897"/> + <source>none</source> + <translation>Š½ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1655"/> + <source>%sNIC %d Rule(%d): name = %s, protocol = %s, host ip = %s, host port = %s, guest ip = %s, guest port = %s +</source> + <translation>%sNIC %d ŠŃŠ°Š²ŠøŠ»Š¾(%d): ŠøŠ¼Ń = %s, ŠæŃŠ¾ŃŠ¾ŠŗŠ¾Š» = %s, Ń
Š¾ŃŃ ip = %s, Ń
Š¾ŃŃ ŠæŠ¾ŃŃ = %s, Š³Š¾ŃŃŠµŠ²Š¾Š¹ ip = %s, Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŠæŠ¾ŃŃ = %s +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1678"/> + <source>NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d) +</source> + <translation>NIC %d ŠŠ°ŃŃŃŠ¾Š¹ŠŗŠø: MTU: %d, Š”Š¾ŠŗŠµŃ (Š¾ŃŠæŃŠ°Š²Š»ŠµŠ½Š¾: %d, ŠæŃŠøŠ½ŃŃŠ¾: %d), ŠŠŗŠ½Š¾ TCP (Š¾ŃŠæŃŠ°Š²Š»ŠµŠ½Š¾:%d, ŠæŃŠøŠ½ŃŃŠ¾: %d) +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1694"/> + <source>Bridged Interface '%ls'</source> + <translation>ŠŠ½ŃŠµŃŃŠµŠ¹Ń Š”ŠµŃŠµŠ²Š¾Š³Š¾ ŠŠ¾ŃŃŠ° '%ls'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1708"/> + <source>Internal Network '%s'</source> + <translation>ŠŠ½ŃŃŃŠµŠ½Š½ŃŃ Š”ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1722"/> + <source>Host-only Interface '%ls'</source> + <translation>ŠŠ½ŃŠµŃŃŠµŠ¹Ń ŠŠøŃŃŃŠ°Š»ŃŠ½Š¾Š¹ Š”ŠµŃŠø '%s'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1737"/> + <source>Generic '%ls'</source> + <translation>ŠŠ±ŃŠøŠ¹ '%ls'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1766"/> + <source>NAT Network '%s'</source> + <translation>Š”ŠµŃŃ NAT '%s'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1781"/> + <source>Host Only Network '%s'</source> + <translation>ŠŠøŃŃŃŠ°Š»ŃŠ½Š°Ń Š”ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1797"/> + <source>Cloud Network '%s'</source> + <translation>ŠŠ±Š»Š°ŃŠ½Š°Ń Š”ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1820"/> + <source>deny</source> + <translation>Š·Š°ŠæŃŠµŃŠøŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1821"/> + <source>allow-vms</source> + <translation>ŃŠ°Š·ŃŠµŃŠøŃŃ Š²Š¼</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1822"/> + <source>allow-all</source> + <translation>ŃŠ°Š·ŃŠµŃŠøŃŃ Š²ŃŠµŠ¼</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1888"/> + <source>%-28s MAC: %ls, Attachment: %s, Cable connected: %s, Trace: %s (file: %ls), Type: %s, Reported speed: %d Mbps, Boot priority: %d, Promisc Policy: %s, Bandwidth group: %ls +</source> + <translation>%-28s MAC: %ls, ŠŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŠµ: %s, ŠŠ°Š±ŠµŠ»Ń ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½: %s, Š¢ŃŠ°ŃŃŠøŃŠ¾Š²ŠŗŠ°: %s (ŃŠ°Š¹Š»: %ls), Š¢ŠøŠæ: %s, ŠŠ°ŃŠ²Š»ŠµŠ½Š½Š°Ń Š”ŠŗŠ¾ŃŠ¾ŃŃŃ: %d MŠ±/Ń, ŠŃŠøŠ¾ŃŠøŃŠµŃ Š·Š°Š³ŃŃŠ·ŠŗŠø: %d, ŠŠ¾Š»ŠøŃŠŗŠ° ŠŠµŃŠ°Š·Š±Š¾ŃŃŠøŠ²Š¾ŃŃŠø: %s, ŠŃŃŠæŠæŠ° ŠŠ¾Š»Š¾ŃŃ ŠŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1918"/> + <source>PS/2 Mouse</source> + <translation>PS/2 ŠŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1922"/> + <source>USB Mouse</source> + <translation>USB ŠŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1926"/> + <source>USB Tablet</source> + <translation>USB ŠŠ»Š°Š½ŃŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1930"/> + <source>USB Tablet and PS/2 Mouse</source> + <translation>USB ŠŠ»Š°Š½ŃŠµŃ Šø PS/2 ŠŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1934"/> + <source>USB Multi-Touch</source> + <translation>USB ŠŃŠ»ŃŃŠøŃŠ°Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1940"/> + <source>Pointing Device:</source> + <translation>Š£ŠŗŠ°Š·Š°ŃŠµŠ»ŃŠ½Š¾Šµ Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1954"/> + <source>PS/2 Keyboard</source> + <translation>PS/2 ŠŠ»Š°Š²ŠøŠ°ŃŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1958"/> + <source>USB Keyboard</source> + <translation>USB ŠŠ»Š°Š²ŠøŠ°ŃŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1962"/> + <source>USB and PS/2 Keyboard</source> + <translation>USB Šø PS/2 ŠŠ»Š°Š²ŠøŠ°ŃŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1968"/> + <source>Keyboard Device:</source> + <translation>ŠŠ»Š°Š²ŠøŠ°ŃŃŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1982"/> + <source>UART %u:</source> + <translation>UART %u:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2011"/> + <location filename="../VBoxManageInfo.cpp" line="2111"/> + <source>%-28s I/O base: %#06x, IRQ: %d</source> + <translation>%-28s ŠŠ°Š·Š° I/O: %#06x, IRQ: %d</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2019"/> + <source>, disconnected</source> + <translation>, Š¾ŃŃŠ¾ŠµŠ“ŠøŠ½ŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2026"/> + <source>, attached to raw file '%ls' +</source> + <translation>, ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ Šŗ raw ŃŠ°Š¹Š»Ń '%ls' +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2034"/> + <source>, attached to tcp (%s) '%ls'</source> + <translation>, ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ Šŗ tcp (%s) '%ls'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2035"/> + <location filename="../VBoxManageInfo.cpp" line="2043"/> + <source>server</source> + <translation>ŃŠµŃŠ²ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2035"/> + <location filename="../VBoxManageInfo.cpp" line="2043"/> + <source>client</source> + <translation>ŠŗŠ»ŠøŠµŠ½Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2042"/> + <source>, attached to pipe (%s) '%ls'</source> + <translation>, ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ Šŗ pipe (%s) '%ls'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2050"/> + <source>, attached to device '%ls'</source> + <translation>, ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ Šŗ ŃŃŃŃŠ¾Š¹ŃŃŠ²Ń '%ls'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2088"/> + <source>LPT %u:</source> + <translation>LPT %u:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2115"/> + <source>, attached to device '%ls' +</source> + <translation>, ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ Šŗ ŃŃŃŃŠ¾Š¹ŃŃŠ²Ń '%ls' +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2240"/> + <source>Audio:</source> + <translation>ŠŃŠ“ŠøŠ¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2242"/> + <source> (Driver: %s, Controller: %s, Codec: %s)</source> + <translation> (ŠŃŠ°Š¹Š²ŠµŃ: %s, ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ: %s, ŠŠ¾Š“ŠµŠŗ: %s)</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2245"/> + <source>Audio playback:</source> + <translation>ŠŃŠ“ŠøŠ¾ Š²Š¾ŃŠæŃŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2246"/> + <source>Audio capture:</source> + <translation>ŠŃŠ“ŠøŠ¾ Š·Š°Ń
Š²Š°Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2260"/> + <location filename="../VBoxManageInfo.cpp" line="2289"/> + <source>HostToGuest</source> + <translation>Š„Š¾ŃŃ->ŠŠ¾ŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2263"/> + <location filename="../VBoxManageInfo.cpp" line="2292"/> + <source>GuestToHost</source> + <translation>ŠŠ¾ŃŃŃ->Š„Š¾ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2266"/> + <location filename="../VBoxManageInfo.cpp" line="2295"/> + <source>Bidirectional</source> + <translation>ŠŠ²ŃŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½Š½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2272"/> + <source>Clipboard Mode:</source> + <translation>Š ŠµŠ¶ŠøŠ¼ Š±ŃŃŠµŃŠ° Š¾Š±Š¼ŠµŠ½Š°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2274"/> + <source>Clipboard file transfers:</source> + <translation>ŠŠµŃŠµŠ“Š°ŃŠ° ŃŠ°Š¹Š»Š¾Š² ŃŠµŃŠµŠ· Š±ŃŃŠµŃ Š¾Š±Š¼ŠµŠ½Š°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2301"/> + <source>Drag and drop Mode:</source> + <translation>Š ŠµŠ¶ŠøŠ¼ Drag and Drop:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2312"/> + <source>Session name:</source> + <translation>ŠŠ¼Ń ŃŠµŃŃŠøŠø:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2345"/> + <source>unknown status</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½ŃŠ¹ ŃŃŠ°ŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2348"/> + <source>blank</source> + <translation>ŠæŃŃŃŠ¾Š¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2353"/> + <source>Video mode:</source> + <translation>ŠŠøŠ“ŠµŠ¾ ŃŠµŠ¶ŠøŠ¼:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2394"/> + <source>null</source> + <translation>ŠæŃŃŃŠ¾</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2400"/> + <source>external</source> + <translation>Š²Š½ŠµŃŠ½ŠøŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2406"/> + <source>guest</source> + <translation>Š³Š¾ŃŃŠµŠ²Š¾Š¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2451"/> + <source>%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s) +</source> + <translation>%-28s Š²ŠŗŠ»ŃŃŠµŠ½ (ŠŠ“ŃŠµŃ %ls, ŠŠ¾ŃŃŃ %ls, ŠŠ½Š¾Š³Š¾ Š”Š¾ŠµŠ“ŠøŠ½ŠµŠ½ŠøŠ¹: %s, ŠŠ“Š½Š¾ Š”Š¾ŠµŠ“ŠøŠ½ŠµŠ½ŠøŠµ : %s, Š¢ŠøŠæ ŠŃŃŠµŠ½ŃŠøŃŠøŠŗŠ°ŃŠøŠø: %s) +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2455"/> + <source>VRDE port:</source> + <translation>ŠŠ¾ŃŃ VRDE:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2457"/> + <source>%-28s enabled (Quality %ls) +</source> + <translation>%-28s Š²ŠŗŠ»ŃŃŠµŠ½ (ŠŠ°ŃŠµŃŃŠ²Š¾ %ls) +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2457"/> + <location filename="../VBoxManageInfo.cpp" line="2459"/> + <source>Video redirection:</source> + <translation>ŠŠøŠ“ŠµŠ¾ ŠæŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2479"/> + <source>%-28s: %-10lS = <not set> +</source> + <translation>%-28s: %-10lS = <Š½Šµ Š·Š°Š“Š°Š½> +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2479"/> + <location filename="../VBoxManageInfo.cpp" line="2481"/> + <source>VRDE property</source> + <translation>Š”Š²Š¾Š¹ŃŃŠ²Š¾ VRDE</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2552"/> + <source>Index:</source> + <translation>ŠŠ½Š“ŠµŠŗŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2553"/> + <source>yes</source> + <translation>Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2553"/> + <source>no</source> + <translation>Š½ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="840"/> + <source>VendorId:</source> + <translation>ID ŠæŠ¾ŃŃŠ°Š²ŃŠøŠŗŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="841"/> + <source>ProductId:</source> + <translation>ID ŠæŃŠ¾Š“ŃŠŗŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="850"/> + <source>Revision:</source> + <translation>Š ŠµŠ²ŠøŠ·ŠøŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="852"/> + <source>Manufacturer:</source> + <translation>ŠŃŠ¾ŠøŠ·Š²Š¾Š“ŠøŃŠµŠ»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="853"/> + <source>Product:</source> + <translation>ŠŃŠ¾Š“ŃŠŗŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2567"/> + <source>Masked Interfaces:</source> + <translation>Š”ŠŗŃŃŃŃŠµ ŠŠ½ŃŠµŃŃŠµŠ¹ŃŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="854"/> + <source>SerialNumber:</source> + <translation>Š”ŠµŃŠøŠ¹Š½ŃŠ¹ ŠŠ¾Š¼ŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="855"/> + <source>Address:</source> + <translation>ŠŠ“ŃŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2604"/> + <source> +Attached physical PCI devices: + +</source> + <translation> +ŠŠ¾Š“ŠŗŠ»ŃŃŠµŠ½Š½ŃŠµ ŃŠøŠ·ŠøŃŠµŃŠŗŠøŠµ PCI ŃŃŃŃŠ¾Š¹ŃŃŠ²Š°: + +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2623"/> + <source> Host device %ls at %s attached as %s +</source> + <translation> Š„Š¾ŃŃ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾ %ls Š² %s, ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½Š½Š¾Šµ ŠŗŠ°Šŗ %s +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2652"/> + <source>Shared folders:</source> + <translation>ŠŠ±ŃŠøŠµ ŠŠ°ŠæŠŗŠø:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2662"/> + <source>global mapping</source> + <translation>Š³Š»Š¾Š±Š°Š»ŃŠ½Š¾Šµ Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2674"/> + <source>machine mapping</source> + <translation>Š¼Š°ŃŠøŠ½Š½Š¾Šµ Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2686"/> + <source>transient mapping</source> + <translation>Š²ŃŠµŠ¼ŠµŠ½Š½Š¾Šµ Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="709"/> + <location filename="../VBoxManageInfo.cpp" line="2693"/> + <source><none> +</source> + <translation><Š½ŠµŃ> +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1502"/> + <location filename="../VBoxManageInfo.cpp" line="1542"/> + <source>Storage Controllers:</source> + <translation>ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŃ Š½Š¾ŃŠøŃŠµŠ»ŠµŠ¹:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1532"/> + <source>#%u: '%ls', Type: %s, Instance: %u, Ports: %u (max %u), %s +</source> + <translation>#%u: '%ls', Š¢ŠøŠæ: %s, ŠŠŗŠ·ŠµŠ¼ŠæŠ»ŃŃ: %u, ŠŠ¾ŃŃŃ: %u (Š¼Š°ŠŗŃ. %u), %s +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1534"/> + <source>Bootable</source> + <translation>ŠŠ°Š³ŃŃŠ·Š¾ŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1534"/> + <source>Not bootable</source> + <translation>ŠŠµŠ·Š°Š³ŃŃŠ·Š¾ŃŠ½ŃŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2546"/> + <source>USB Device Filters: +</source> + <translation>Š¤ŠøŠ»ŃŃŃŃ USB ŃŃŃŃŠ¾Š¹ŃŃŠ²: +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2553"/> + <source> Active:</source> + <translation> ŠŠŗŃŠøŠ²Š½Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2554"/> + <source> Name:</source> + <translation> ŠŠ¼Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2555"/> + <source> VendorId:</source> + <translation> ID ŠæŠ¾ŃŃŠ°Š²ŃŠøŠŗŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2556"/> + <source> ProductId:</source> + <translation> ID ŠæŃŠ¾Š“ŃŠŗŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2557"/> + <source> Revision:</source> + <translation> Š ŠµŠ²ŠøŠ·ŠøŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2558"/> + <source> Manufacturer:</source> + <translation> ŠŃŠ¾ŠøŠ·Š²Š¾Š“ŠøŃŠµŠ»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2559"/> + <source> Product:</source> + <translation> ŠŃŠ¾Š“ŃŠŗŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2560"/> + <source> Remote:</source> + <translation> Š£Š“Š°Š»ŠµŠ½Š½Š¾Šµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2561"/> + <source> Serial Number:</source> + <translation> Š”ŠµŃŠøŠ¹Š½ŃŠ¹ Š½Š¾Š¼ŠµŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2572"/> + <source>USB Device Filters:</source> + <translation>Š¤ŠøŠ»ŃŃŃŃ USB ŃŃŃŃŠ¾Š¹ŃŃŠ²:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2580"/> + <source>Available remote USB devices:</source> + <translation>ŠŠ¾ŃŃŃŠæŠ½ŃŠµ ŃŠ“Š°Š»ŠµŠ½Š½ŃŠµ USB ŃŃŃŃŠ¾Š¹ŃŃŠ²Š°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2588"/> + <source>Currently attached USB devices:</source> + <translation>Š”ŠµŠ¹ŃŠ°Ń ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½Š½ŃŠµ USB ŃŃŃŃŠ¾Š¹ŃŃŠ²Š°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2639"/> + <source>Bandwidth groups:</source> + <translation>ŠŃŃŠæŠæŃ ŠæŠ¾Š»Š¾ŃŃ ŠæŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2738"/> + <source>VRDE Connection:</source> + <translation>VRDE Š”Š¾ŠµŠ“ŠøŠ½ŠµŠ½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2738"/> + <location filename="../VBoxManageInfo.cpp" line="2828"/> + <location filename="../VBoxManageInfo.cpp" line="2830"/> + <source>active</source> + <translation>Š°ŠŗŃŠøŠ²Š½Š¾Šµ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2739"/> + <source>Clients so far:</source> + <translation>ŠŠ»ŠøŠµŠ½ŃŃ Š½Š° Š“Š°Š½Š½ŃŠ¹ Š¼Š¾Š¼ŠµŠ½Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2746"/> + <source>Start time:</source> + <translation>ŠŃŠµŠ¼Ń ŃŃŠ°ŃŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2749"/> + <source>Last started:</source> + <translation>ŠŠ¾ŃŠ»ŠµŠ“Š½ŠøŠ¹ ŃŠ°Š· Š½Š°ŃŠ°ŃŠ¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2751"/> + <source>Last ended:</source> + <translation>ŠŠ¾ŃŠ»ŠµŠ“Š½ŠøŠ¹ ŃŠ°Š· Š·Š°ŠŗŠ¾Š½ŃŠµŠ½Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2761"/> + <source>Sent:</source> + <translation>ŠŃŠæŃŠ°Š²Š»ŠµŠ½Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2761"/> + <location filename="../VBoxManageInfo.cpp" line="2763"/> + <location filename="../VBoxManageInfo.cpp" line="2765"/> + <location filename="../VBoxManageInfo.cpp" line="2767"/> + <source>Bytes</source> + <translation>ŠŠ°Š¹Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2762"/> + <source>Average speed:</source> + <translation>Š”ŃŠµŠ“Š½ŃŃ ŃŠŗŠ¾ŃŠ¾ŃŃŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2762"/> + <location filename="../VBoxManageInfo.cpp" line="2766"/> + <source>B/s</source> + <translation>Š/Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2763"/> + <source>Sent total:</source> + <translation>ŠŃŠµŠ³Š¾ Š¾ŃŠæŃŠ°Š²Š»ŠµŠ½Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2765"/> + <source>Received:</source> + <translation>ŠŠ¾Š»ŃŃŠµŠ½Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2766"/> + <source>Speed:</source> + <translation>Š”ŠŗŠ¾ŃŠ¾ŃŃŃ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2767"/> + <source>Received total:</source> + <translation>ŠŃŠµŠ³Š¾ ŠæŠ¾Š»ŃŃŠµŠ½Š¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2771"/> + <source>User name:</source> + <translation>ŠŠ¼Ń ŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2772"/> + <source>Domain:</source> + <translation>ŠŠ¾Š¼ŠµŠ½:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2773"/> + <source>Client name:</source> + <translation>ŠŠ¼Ń ŠŗŠ»ŠøŠµŠ½ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2774"/> + <source>Client IP:</source> + <translation>IP ŠŗŠ»ŠøŠµŠ½ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2775"/> + <source>Client version:</source> + <translation>ŠŠµŃŃŠøŃ ŠŗŠ»ŠøŠµŠ½ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2776"/> + <source>Encryption:</source> + <translation>ŠØŠøŃŃŠ¾Š²Š°Š½ŠøŠµ:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2828"/> + <source>Capturing:</source> + <translation>ŠŠ°Ń
Š²Š°Ń:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2830"/> + <source>Capture audio:</source> + <translation>ŠŠ°Ń
Š²Š°Ń Š°ŃŠ“ŠøŠ¾:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2840"/> + <source>Capture screens:</source> + <translation>ŠŠ°Ń
Š²Š°Ń ŃŠŗŃŠ°Š½Š¾Š²:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2841"/> + <source>Capture file:</source> + <translation>Š¤Š°Š¹Š» Š·Š°Ń
Š²Š°ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2843"/> + <source>Capture dimensions:</source> + <translation>Š Š°Š·Š¼ŠµŃŃ Š·Š°Ń
Š²Š°ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2844"/> + <source>Capture rate:</source> + <translation>ŠŠøŃŃŠµŠ¹Ń Š·Š°Ń
Š²Š°ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2844"/> + <location filename="../VBoxManageInfo.cpp" line="2845"/> + <source>kbps</source> + <translation>ŠŗŠ±/Ń</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2845"/> + <source>Capture FPS:</source> + <translation>FPS Š·Š°Ń
Š²Š°ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2846"/> + <source>Capture options:</source> + <translation>ŠŠæŃŠøŠø Š·Š°Ń
Š²Š°ŃŠ°:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2863"/> + <source>Description: +%ls +</source> + <translation>ŠŠæŠøŃŠ°Š½ŠøŠµ +%ls +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2919"/> + <source>MB</source> + <translation>ŠŠ</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2919"/> + <source>Configured memory balloon:</source> + <translation>ŠŠ°ŃŃŃŠ¾ŠµŠ½Š½ŃŠ¹ balloon ŠæŠ°Š¼ŃŃŠø:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2927"/> + <source>OS type:</source> + <translation>Š¢ŠøŠæ ŠŠ”:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2932"/> + <source>Additions run level:</source> + <translation>Š£ŃŠ¾Š²ŠµŠ½Ń Š²ŃŠæŠ¾Š»Š½ŠµŠ½ŠøŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2944"/> + <source>Additions version:</source> + <translation>ŠŠµŃŃŠøŃ ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹:</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2973"/> + <source>Facility "%ls": %s (last update: %s) +</source> + <translation>Š”ŃŠµŠ“ŃŃŠ²Š¾ "%ls": %s (ŠæŠ¾ŃŠ»ŠµŠ“Š½ŠµŠµ Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠµ: %s) +</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="3044"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="3054"/> + <source>VM name or UUID required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠøŠ¼Ń ŠŠ ŠøŠ»Šø UUID</translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="3065"/> + <source>Option --log is exclusive</source> + <translation>ŠŠæŃŠøŃ --log ŃŠŗŃŠŗŠ»ŃŠ·ŠøŠ²Š½Š°Ń</translation> + </message> +</context> +<context> + <name>Internal</name> + <message> + <location filename="../VBoxInternalManage.cpp" line="169"/> + <source>Usage: VBoxManage internalcommands <command> [command arguments] + +Commands: + +%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%sWARNING: This is a development tool and shall only be used to analyse + problems. It is completely unsupported and will change in + incompatible ways without warning. +</source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½ŠøŠµ: VBoxManage internalcommands <ŠŗŠ¾Š¼Š°Š½Š“Š°> [Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŃ ŠŗŠ¾Š¼Š°Š½Š“Ń] + +ŠŠ¾Š¼Š°Š½Š“Ń: + +%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%sŠŠ ŠŠŠ£ŠŠ ŠŠŠŠŠŠŠ: ŠŃŠ¾ ŠøŠ½ŃŃŃŃŠ¼ŠµŠ½Ń ŃŠ°Š·ŃŠ°Š±Š¾ŃŃŠøŠŗŠ° Šø Š“Š¾Š»Š¶ŠµŠ½ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŃŃŃ + ŃŠ¾Š»ŃŠŗŠ¾ Š“Š»Ń Š°Š½Š°Š»ŠøŠ·Š° ŠæŃŠ¾Š±Š»ŠµŠ¼. ŠŠ½ Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ Š²Š¾Š¾Š±ŃŠµ + Šø Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½ Š±ŠµŠ· ŠæŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŃ Šø Š±ŠµŠ· ŃŠ¾Ń
ŃŠ°Š½ŠµŠ½ŠøŃ + ŃŠ¾Š²Š¼ŠµŃŃŠøŠ¼Š¾ŃŃŠø. +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="180"/> + <source> loadmap <vmname|uuid> <symfile> <address> [module] [subtrahend] [segment] + This will instruct DBGF to load the given map file + during initialization. (See also loadmap in the debugger.) + +</source> + <translation> loadmap <ŠøŠ¼Ń Š²Š¼|uuid> <ŃŠ°Š¹Š» ŃŠøŠ¼Š²Š¾Š»Š¾Š²> <Š°Š“ŃŠµŃ> [module] [subtrahend] [segment] + ŠŠ½Š° Š³Š¾Š²Š¾ŃŠøŃ DBGF Š·Š°Š³ŃŃŠ·ŠøŃŃ ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ map ŃŠ°Š¹Š» Š²Š¾ Š²ŃŠµŠ¼Ń + ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·Š°ŃŠøŠø. (Š”Š¼Š¾ŃŃŠø loadmap Ń Š¾ŃŠ»Š°Š“ŃŠøŠŗŠ°.) + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="187"/> + <source> loadsyms <vmname|uuid> <symfile> [delta] [module] [module address] + This will instruct DBGF to load the given symbol file + during initialization. + +</source> + <translation> loadmap <ŠøŠ¼Ń Š²Š¼|uuid> <ŃŠ°Š¹Š» ŃŠøŠ¼Š²Š¾Š»Š¾Š²> [delta] [module] [module address] + ŠŠ½Š° Š³Š¾Š²Š¾ŃŠøŃ DBGF Š·Š°Š³ŃŃŠ·ŠøŃŃ ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠ°Š¹Š» ŃŠøŠ¼Š²Š¾Š»Š¾Š² + Š²Š¾ Š²ŃŠµŠ¼Ń ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·Š°ŃŠøŠø. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="194"/> + <source> sethduuid <filepath> [<uuid>] + Assigns a new UUID to the given image file. This way, multiple copies + of a container can be registered. + +</source> + <translation> sethduuid <ŠæŃŃŃ Šŗ ŃŠ°Š¹Š»Ń> [<uuid>] + ŠŠ°Š·Š½Š°ŃŠ°ŠµŃ Š½Š¾Š²ŃŠ¹ UUID Š“Š°Š½Š½Š¾Š¼Ń ŃŠ°Š¹Š»Ń Š¾Š±ŃŠ°Š·Š°. Š¢Š°ŠŗŠøŠ¼ Š¾Š±ŃŠ°Š·Š¾Š¼, Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ + Š·Š°ŃŠµŠ³ŠøŃŃŃŠøŃŠ¾Š²Š°Š½Š¾ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŠŗŠ¾ŠæŠøŠ¹ Š¾Š“Š½Š¾Š³Š¾ Šø ŃŠ¾Š³Š¾ Š¶Šµ ŠŗŠ¾Š½ŃŠµŠ¹Š½ŠµŃŠ°. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="201"/> + <source> sethdparentuuid <filepath> <uuid> + Assigns a new parent UUID to the given image file. + +</source> + <translation> sethdparentuuid <ŠæŃŃŃ Šŗ ŃŠ°Š¹Š»Ń> <uuid> + ŠŠ°Š·Š½Š°ŃŠ°ŠµŃ Š½Š¾Š²ŃŠ¹ ŃŠ¾Š“ŠøŃŠµŠ»ŃŃŠŗŠøŠ¹ UUID Š“Š°Š½Š½Š¾Š¼Ń ŃŠ°Š¹Š»Ń Š¾Š±ŃŠ°Š·Š°. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="207"/> + <source> dumphdinfo <filepath> + Prints information about the image at the given location. + +</source> + <translation> dumphdinfo <ŠæŃŃŃ Šŗ ŃŠ°Š¹Š»Ń> + ŠŃŠ²Š¾Š“ŠøŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾Š± Š¾Š±ŃŠ°Š·Šµ ŠæŠ¾ ŃŠŗŠ°Š·Š°Š½Š½Š¾Š¼Ń ŃŠ°ŃŠæŠ¾Š»Š¾Š¶ŠµŠ½ŠøŃ. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="213"/> + <source> listpartitions -rawdisk <diskname> + Lists all partitions on <diskname>. + +</source> + <translation> listpartitions -rawdisk <ŠøŠ¼Ń Š“ŠøŃŠŗŠ°> + ŠŠµŃŠµŃŠøŃŠ»ŠøŃŃ Š²ŃŠµ ŃŠ°Š·Š“ŠµŠ»Ń Š½Š° <ŠøŠ¼Ń Š“ŠøŃŠŗŠ°>. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="219"/> + <source> createrawvmdk -filename <filename> -rawdisk <diskname> + [-partitions <list of partition numbers> [-mbr <filename>] ] + [-relative] + Creates a new VMDK image which gives access to an entire host disk (if + the parameter -partitions is not specified) or some partitions of a + host disk. If access to individual partitions is granted, then the + parameter -mbr can be used to specify an alternative MBR to be used + (the partitioning information in the MBR file is ignored). + The diskname is on Linux e.g. /dev/sda, and on Windows e.g. + \\.\PhysicalDrive0). + On Linux or FreeBSD host the parameter -relative causes a VMDK file to + be created which refers to individual partitions instead to the entire + disk. + The necessary partition numbers can be queried with + VBoxManage internalcommands listpartitions + +</source> + <translation> createrawvmdk -filename <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°> -rawdisk <ŠøŠ¼Ń Š“ŠøŃŠŗŠ°> + [-partitions <ŃŠæŠøŃŠ¾Šŗ Š½Š¾Š¼ŠµŃŠ¾Š² ŃŠ°Š·Š“ŠµŠ»Š¾Š²> [-mbr <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°>] ] + [-relative] + Š”Š¾Š·Š“Š°ŠµŃ Š½Š¾Š²ŃŠ¹ Š¾Š±ŃŠ°Š· VMDK, ŠŗŠ¾ŃŠ¾ŃŃŠ¹ Š“Š°ŠµŃ Š“Š¾ŃŃŃŠæ ŠŗŠ¾ Š²ŃŠµŠ¼Ń Š“ŠøŃŠŗŃ (ŠµŃŠ»Šø + ŠæŠ°ŃŠ°Š¼ŠµŃŃ -partitions Š½Šµ ŃŠŗŠ°Š·Š°Š½) ŠøŠ»Šø Šŗ Š½ŠµŠŗŠ¾ŃŠ¾ŃŃŠ¼ ŃŠ°Š·Š“ŠµŠ»Š°Š¼ Š“ŠøŃŠŗŠ° Ń
Š¾ŃŃŠ°. + ŠŃŠ»Šø Š“Š¾ŃŃŃŠæ Šŗ ŠŗŠ¾Š½ŠŗŃŠµŃŠ½ŃŠ¼ ŃŠ°Š·Š“ŠµŠ»Š°Š¼ ŃŠ°Š·ŃŠµŃŠµŠ½, ŠæŠ°ŃŠ°Š¼ŠµŃŃ -mbr Š¼Š¾Š¶ŠµŃ + ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°ŃŃŃŃ Š“Š»Ń ŃŠŗŠ°Š·Š°Š½ŠøŃ Š°Š»ŃŃŠµŃŠ½Š°ŃŠøŠ²Š½Š¾Š³Š¾ MBR (ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾ ŃŠ°Š·Š“ŠµŠ»Š°Ń
+ Š² MBR ŃŠ°Š¹Š»Šµ ŠøŠ³Š½Š¾ŃŠøŃŃŠµŃŃŃ). ŠŠ¼Ń Š“ŠøŃŠŗŠ° Š² Linux - ŃŃŠ¾ Š½Š°ŠæŃŠøŠ¼ŠµŃ /dev/sda, + Š° Š² Windows - Š½Š°ŠæŃŠøŠ¼ŠµŃ \\.\PhysicalDrive0. + Š Ń
Š¾ŃŃŠ°Ń
Linux ŠøŠ»Šø FreeBSD, ŠæŠ°ŃŠ°Š¼ŠµŃŃ -relative Š·Š°ŃŃŠ°Š²Š»ŃŠµŃ ŃŠ¾Š·Š“Š°ŃŃ ŃŠ°Š¹Š» + VMDK, ŃŃŃŠ»Š°ŃŃŠøŠ¹ŃŃ Š½Š° ŠøŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½ŃŠµ ŃŠ°Š·Š“ŠµŠ»Ń Š²Š¼ŠµŃŃŠ¾ Š²ŃŠµŠ³Š¾ Š“ŠøŃŠŗŠ°. + ŠŠµŠ¾Š±Ń
Š¾Š“ŠøŠ¼ŃŠµ Š½Š¾Š¼ŠµŃŠ° ŃŠ°Š·Š“ŠµŠ»Š¾Š² Š¼Š¾Š³ŃŃ Š±ŃŃŃ ŠæŠ¾Š»ŃŃŠµŠ½Ń ŃŠµŃŠµŠ· + VBoxManage internalcommands listpartitions + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="238"/> + <source> renamevmdk -from <filename> -to <filename> + Renames an existing VMDK image, including the base file and all its extents. + +</source> + <translation> renamevmdk -from <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°> -to <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°> + ŠŠµŃŠµŠ¼ŠµŠ½Š¾Š²ŃŠ²Š°ŠµŃ ŃŃŃŠµŃŃŠ²ŃŃŃŠøŠ¹ VMDK Š¾Š±ŃŠ°Š·, Š²ŠŗŠ»ŃŃŠ°ŃŃ Š±Š°Š·Š¾Š²ŃŠ¹ ŃŠ°Š¹Š» Šø Š²ŃŠµ ŠµŠ³Š¾ ŃŠŗŃŃŠµŠ½ŃŃ. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="245"/> + <source> converttoraw [-format <fileformat>] <filename> <outputfile>|stdout + Convert image to raw, writing to file or stdout. + +</source> + <translation> converttoraw [-format <ŃŠ¾ŃŠ¼Š°Ń ŃŠ°Š¹Š»Š°>] <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°> <Š²ŃŃ
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»>|stdout + ŠŃŠµŠ¾Š±ŃŠ°Š·ŃŠµŃ Š¾Š±ŃŠ°Š· Š² raw, Š·Š°ŠæŠøŃŃŠ²Š°Ń Š² ŃŠ°Š¹Š» ŠøŠ»Šø stdout. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="251"/> + <source> converttoraw [-format <fileformat>] <filename> <outputfile> + Convert image to raw, writing to file. + +</source> + <translation> converttoraw [-format <ŃŠ¾ŃŠ¼Š°Ń ŃŠ°Š¹Š»Š°>] <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°> <Š²ŃŃ
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»> + ŠŃŠµŠ¾Š±ŃŠ°Š·ŃŠµŃ Š¾Š±ŃŠ°Š· Š² raw, Š·Š°ŠæŠøŃŃŠ²Š°Ń Š² ŃŠ°Š¹Š». + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="259"/> + <source> converthd [-srcformat VDI|VMDK|VHD|RAW] + [-dstformat VDI|VMDK|VHD|RAW] + <inputfile> <outputfile> + converts hard disk images between formats + +</source> + <translation> converthd [-srcformat VDI|VMDK|VHD|RAW] + [-dstformat VDI|VMDK|VHD|RAW] + <Š²Ń
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»> <Š²ŃŃ
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»> + ŠæŃŠµŠ¾Š±ŃŠ°Š·ŃŠµŃ Š¾Š±ŃŠ°Š·Ń Š¶ŠµŃŃŠŗŠøŃ
Š“ŠøŃŠŗŠ¾Š² Š² ŃŠ°Š·Š½ŃŠµ ŃŠ¾ŃŠ¼Š°ŃŃ + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="267"/> + <source> repairhd [-dry-run] + [-format VDI|VMDK|VHD|...] + <filename> + Tries to repair corrupted disk images + +</source> + <translation> repairhd [-dry-run] + [-format VDI|VMDK|VHD|...] + <ŠøŠ¼Ń ŃŠ°Š¹Š»Š°> + ŠŃŃŠ°ŠµŃŃŃ Š²Š¾ŃŃŃŠ°Š½Š¾Š²ŠøŃŃ ŠæŠ¾Š²ŃŠµŠ¶Š“ŠµŠ½Š½ŃŠ¹ Š¾Š±ŃŠ°Š· Š“ŠøŃŠŗŠ° + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="276"/> + <source> modinstall + Installs the necessary driver for the host OS + +</source> + <translation> modinstall + Š£ŃŃŠ°Š½Š°Š²Š»ŠøŠ²Š°ŠµŃ Š½ŃŠ¶Š½ŃŠ¹ Š“ŃŠ°Š¹Š²ŠµŃ Š² ŠŠ” Ń
Š¾ŃŃŠ° + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="282"/> + <source> moduninstall + Deinstalls the driver + +</source> + <translation> moduninstall + Š£Š“Š°Š»ŃŠµŃ Š“ŃŠ°Š¹Š²ŠµŃ + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="292"/> + <source> debuglog <vmname|uuid> [--enable|--disable] [--flags todo] + [--groups todo] [--destinations todo] + Controls debug logging. + +</source> + <translation> debuglog <ŠøŠ¼Ń Š²Š¼|uuid> [--enable|--disable] [--flags todo] + [--groups todo] [--destinations todo] + ŠŠ¾Š½ŃŃŠ¾Š»ŠøŃŃŠµŃ Š¾ŃŠ»Š°Š“Š¾ŃŠ½Š¾Šµ Š¶ŃŃŠ½Š°Š»ŠøŃŠ¾Š²Š°Š½ŠøŠµ. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="299"/> + <source> passwordhash <password> + Generates a password hash. + +</source> + <translation> passwordhash <ŠæŠ°ŃŠ¾Š»Ń> + ŠŠµŠ½ŠµŃŠøŃŃŠµŃ Ń
ŃŃ ŠæŠ°ŃŠ¾Š»Ń. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="305"/> + <source> gueststats <vmname|uuid> [--interval <seconds>] + Obtains and prints internal guest statistics. + Sets the update interval if specified. + +</source> + <translation> gueststats <ŠøŠ¼Ń Š²Š¼|uuid> [--interval <ŃŠµŠŗŃŠ½Š“Ń>] + ŠŠ¾Š»ŃŃŠ°ŠµŃ Šø Š²ŃŠ²Š¾Š“ŠøŃ Š²Š½ŃŃŃŠµŠ½Š½ŃŃ ŃŃŠ°ŃŠøŃŃŠøŠŗŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń. + ŠŠ°Š“Š°ŠµŃ ŠøŠ½ŃŠµŃŠ²Š°Š» Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŃ ŠµŃŠ»Šø ŃŠŗŠ°Š·Š°Š½Š¾. + +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="451"/> + <source>Cannot find unique key for '%s'!</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŃŠ½ŠøŠŗŠ°Š»ŃŠ½ŃŠ¹ ŠŗŠ»ŃŃ Š“Š»Ń '%s'!</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="514"/> + <source>Failed to delete key '%s' from '%s', string conversion error %Rrc!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ ŠŗŠ»ŃŃ '%s' ŠøŠ· '%s', Š¾ŃŠøŠ±ŠŗŠ° ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŃ ŃŃŃŠ¾Šŗ %Rrc!</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="538"/> + <source>Failed to set '%s/%s/%s' to '%s'! hrc=%#x</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ '%s/%s/%s' Š² '%s'! hrc=%#x</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="606"/> + <location filename="../VBoxInternalManage.cpp" line="683"/> + <source>Missing the filename argument! +</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń ŠøŠ¼ŠµŠ½Šø ŃŠ°Š¹Š»Š°! +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="614"/> + <source>Failed to read delta '%s', rc=%Rrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ Š“ŠµŠ»ŃŃŃ '%s', rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="626"/> + <location filename="../VBoxInternalManage.cpp" line="691"/> + <source>Failed to read module address '%s', rc=%Rrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ Š°Š“ŃŠµŃ Š¼Š¾Š“ŃŠ»Ń '%s', rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="634"/> + <source>Failed to read module size '%s', rc=%Rrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ ŃŠ°Š·Š¼ŠµŃ Š¼Š¾Š“ŃŠ»Ń '%s', rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="688"/> + <source>Missing the module address argument! +</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Š°Š“ŃŠµŃŠ° Š¼Š¾Š“ŃŠ»Ń! +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="702"/> + <source>Failed to read subtrahend '%s', rc=%Rrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ Š²ŃŃŠøŃŠ°ŠµŠ¼Š¾Šµ '%s', rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="710"/> + <source>Failed to read segment number '%s', rc=%Rrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠµŃŃŃ Š½Š¾Š¼ŠµŃ ŃŠµŠ³Š¼ŠµŠ½ŃŠ° '%s', rc=%Rrc +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="737"/> + <source>Error code %Rrc at %s(%u) in function %s</source> + <translation>ŠŠ¾Š“ Š¾ŃŠøŠ±ŠŗŠø %Rrc Š² %s(%u) Š² ŃŃŠ½ŠŗŃŠøŠø %s</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="760"/> + <location filename="../VBoxInternalManage.cpp" line="774"/> + <location filename="../VBoxInternalManage.cpp" line="832"/> + <source>Not enough parameters</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="765"/> + <location filename="../VBoxInternalManage.cpp" line="776"/> + <source>Invalid UUID parameter</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ UUID ŠæŠ°ŃŠ°Š¼ŠµŃŃ</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="780"/> + <source>Invalid invocation</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²ŃŠ·Š¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="788"/> + <location filename="../VBoxInternalManage.cpp" line="841"/> + <source>Format autodetect failed: %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š°Š²ŃŠ¾Š“ŠµŃŠµŠŗŃŠøŃŠ¾Š²Š°ŃŃ ŃŠ¾ŃŠ¼Š°Ń: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="803"/> + <location filename="../VBoxInternalManage.cpp" line="856"/> + <location filename="../VBoxInternalManage.cpp" line="1958"/> + <location filename="../VBoxInternalManage.cpp" line="2056"/> + <location filename="../VBoxInternalManage.cpp" line="2130"/> + <source>Cannot create the virtual disk container: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŠŗŠ¾Š½ŃŠµŠ¹Š½ŠµŃ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ°: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="808"/> + <location filename="../VBoxInternalManage.cpp" line="861"/> + <source>Cannot open the image: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ Š¾Š±ŃŠ°Š·: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="815"/> + <source>Cannot set a new UUID: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š·Š°Š“Š°ŃŃ Š½Š¾Š²ŃŠ¹ UUID: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="817"/> + <source>UUID changed to: %s +</source> + <translation>UUID ŠøŠ·Š¼ŠµŠ½ŠµŠ½ Š½Š°: %s +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="942"/> + <source>The GPT header seems corrupt because it contains too many entries</source> + <translation>ŠŠ°Š¶ŠµŃŃŃ, GPT Š·Š°Š³Š¾Š»Š¾Š²Š¾Šŗ ŠæŠ¾Š²ŃŠµŠ¶Š“ŠµŠ½, ŠæŠ¾ŃŠ¾Š¼Ń ŃŃŠ¾ Š¾Š½ ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŃŠ»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ ŃŠ»ŠµŠ¼ŠµŠ½ŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="949"/> + <source>Allocating memory for the GPT partitions entries failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠ“ŠµŠ»ŠøŃŃ ŠæŠ°Š¼ŃŃŃ Š“Š»Ń ŃŠ»ŠµŠ¼ŠµŠ½ŃŠ¾Š² GPT ŃŠ°Š·Š“ŠµŠ»Š¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="958"/> + <source>Reading the partition table failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾ŃŠøŃŠ°ŃŃ ŃŠ°Š±Š»ŠøŃŃ ŃŠ°Š·Š“ŠµŠ»Š¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1042"/> + <source>More than one extended partition</source> + <translation>ŠŠ¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°ŃŃŠøŃŠµŠ½Š½Š¾Š³Š¾ ŃŠ°Š·Š“ŠµŠ»Š°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1060"/> + <source>Inconsistency for logical partition start</source> + <translation>ŠŠµŃŠ¾Š³Š»Š°ŃŠ¾Š²Š°Š½Š½Š¾ŃŃŃ Š½Š°ŃŠ°Š»Š° Š»Š¾Š³ŠøŃŠµŃŠŗŠ¾Š³Š¾ ŃŠ°Š·Š“ŠµŠ»Š°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1072"/> + <source>Logical partition without magic</source> + <translation>ŠŠ¾Š³ŠøŃŠµŃŠŗŠøŠ¹ ŃŠ°Š·Š“ŠµŠ» Š±ŠµŠ· magic</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1079"/> + <source>Logical partition with type 0 encountered</source> + <translation>Š”ŃŠ¾Š»ŠŗŠ½ŃŠ»ŠøŃŃ Ń Š»Š¾Š³ŠøŃŠµŃŠŗŠøŠ¼ ŃŠ°Š·Š“ŠµŠ»Š¾Š¼ ŃŠøŠæŠ° 0</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1096"/> + <source>Invalid partition start offset</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŃŠ¼ŠµŃŠµŠ½ŠøŠµ Š½Š°ŃŠ°Š»Š° ŃŠ°Š·Š“ŠµŠ»Š°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1116"/> + <source>Logical partition chain broken</source> + <translation>Š¦ŠµŠæŠ¾ŃŠŗŠ° Š»Š¾Š³ŠøŃŠµŃŠŗŠøŃ
ŃŠ°Š·Š“ŠµŠ»Š¾Š² ŠæŠ¾Š²ŃŠµŠ¶Š“ŠµŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1139"/> + <source>Two partitions start at the same place</source> + <translation>ŠŠ²Š° ŃŠ°Š·Š“ŠµŠ»Š° Š½Š°ŃŠøŠ½Š°ŃŃŃŃ Ń Š¾Š“Š½Š¾Š³Š¾ Šø ŃŠ¾Š³Š¾ Š¶Šµ Š¼ŠµŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1144"/> + <source>Partition starts at sector 0</source> + <translation>Š Š°Š·Š“ŠµŠ» Š½Š°ŃŠøŠ½Š°ŠµŃŃŃ Š² ŃŠµŠŗŃŠ¾ŃŠµ 0</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1180"/> + <source>Overlapping GPT partitions</source> + <translation>ŠŠµŃŠµŠŗŃŃŠ²Š°ŃŃŠøŠµŃŃ GPT ŃŠ°Š·Š“ŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1196"/> + <source>Overlapping MBR partitions</source> + <translation>ŠŠµŃŠµŠŗŃŃŠ²Š°ŃŃŠøŠµŃŃ MBR ŃŠ°Š·Š“ŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1219"/> + <location filename="../VBoxInternalManage.cpp" line="1304"/> + <location filename="../VBoxInternalManage.cpp" line="1313"/> + <location filename="../VBoxInternalManage.cpp" line="1322"/> + <location filename="../VBoxInternalManage.cpp" line="1331"/> + <location filename="../VBoxInternalManage.cpp" line="2018"/> + <location filename="../VBoxInternalManage.cpp" line="2027"/> + <location filename="../VBoxInternalManage.cpp" line="2088"/> + <location filename="../VBoxInternalManage.cpp" line="2251"/> + <location filename="../VBoxInternalManage.cpp" line="2260"/> + <location filename="../VBoxInternalManage.cpp" line="2385"/> + <source>Missing argument to '%s'</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="368"/> + <location filename="../VBoxInternalManage.cpp" line="1226"/> + <location filename="../VBoxInternalManage.cpp" line="1343"/> + <location filename="../VBoxInternalManage.cpp" line="2034"/> + <location filename="../VBoxInternalManage.cpp" line="2107"/> + <location filename="../VBoxInternalManage.cpp" line="2275"/> + <location filename="../VBoxInternalManage.cpp" line="2396"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="327"/> + <source> +Syntax error: %N +</source> + <translation type="unfinished"> +Š”ŠøŠ½ŃŠ°ŠŗŃŠøŃŠµŃŠŗŠ°Ń Š¾ŃŠøŠ±ŠŗŠ°: %N +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="372"/> + <source>Invalid option -%c</source> + <translation type="unfinished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń Š¾ŠæŃŠøŃ -%c</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="373"/> + <source>Invalid option case %i</source> + <translation type="unfinished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²Š°ŃŠøŠ°Š½Ń Š¾ŠæŃŠøŠø %i</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="376"/> + <source>Unknown option: %s</source> + <translation type="unfinished">ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="378"/> + <source>Invalid argument format: %s</source> + <translation type="unfinished">ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠ¾ŃŠ¼Š°Ń Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ°: %s</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1231"/> + <location filename="../VBoxInternalManage.cpp" line="1349"/> + <source>Mandatory parameter -rawdisk missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ -rawdisk</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1236"/> + <source>Cannot open the raw disk: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ raw Š“ŠøŃŠŗ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1242"/> + <source>Number Type StartCHS EndCHS Size (MiB) Start (Sect) +</source> + <translation>ŠŠ¾Š¼ŠµŃ Š¢ŠøŠæ ŠŠ°ŃCHS ŠŠ¾Š½CHS Š Š°Š·Š¼ŠµŃ (MiB) Š”ŃŠ°ŃŃ (Š”ŠµŠŗŃ) +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1347"/> + <source>Mandatory parameter -filename missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ -filename</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1352"/> + <source>The parameter -mbr is only valid when the parameter -partitions is also present</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ -mbr Š“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŠµŠ½ ŃŠ¾Š»ŃŠŗŠ¾ ŠŗŠ¾Š³Š“Š° ŃŠ°ŠŗŠ¶Šµ ŠæŃŠøŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ -partitions</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1361"/> + <source>Cannot open the raw disk '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ raw Š“ŠøŃŠŗ '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1390"/> + <source>File '%s' is no fixed/removable medium device</source> + <translation>Š¤Š°Š¹Š» '%s' Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾Š¼ ŃŠøŠŗŃŠøŃŠ¾Š²Š°Š½Š½Š¾Š³Š¾/ŃŠ¼ŠµŠ½Š½Š¾Š³Š¾ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1407"/> + <source>The -relative parameter is invalid for raw disk %s</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ -relative Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ Š“Š»Ń raw Š“ŠøŃŠŗŠ° %s</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1421"/> + <source>Cannot get the geometry of the raw disk '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ Š³ŠµŠ¾Š¼ŠµŃŃŠøŃ raw Š“ŠøŃŠŗŠ° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1428"/> + <location filename="../VBoxInternalManage.cpp" line="1477"/> + <location filename="../VBoxInternalManage.cpp" line="1602"/> + <source>The -relative parameter is invalid for raw images</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ -relative Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ Š“Š»Ń raw Š¾Š±ŃŠ°Š·Š¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1462"/> + <location filename="../VBoxInternalManage.cpp" line="1556"/> + <location filename="../VBoxInternalManage.cpp" line="1627"/> + <source>Cannot get the size of the raw disk '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ raw Š“ŠøŃŠŗŠ° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1472"/> + <location filename="../VBoxInternalManage.cpp" line="1527"/> + <location filename="../VBoxInternalManage.cpp" line="1565"/> + <source>Failed to get size of file '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ ŃŠ°Š¹Š»Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1484"/> + <source>File '%s' is no block device</source> + <translation>Š¤Š°Š¹Š» '%s' Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ Š±Š»Š¾ŃŠ½ŃŠ¼ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾Š¼</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1492"/> + <location filename="../VBoxInternalManage.cpp" line="1541"/> + <location filename="../VBoxInternalManage.cpp" line="1579"/> + <location filename="../VBoxInternalManage.cpp" line="1618"/> + <source>Failed to get file informtation for raw disk '%s': %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š“Š»Ń raw Š“ŠøŃŠŗŠ° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1509"/> + <source>Cannot get the block size for file '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ Š±Š»Š¾ŠŗŠ° ŃŠ°Š¹Š»Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1517"/> + <location filename="../VBoxInternalManage.cpp" line="1594"/> + <source>Cannot get the block count for file '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ Š±Š»Š¾ŠŗŠ¾Š² Š² ŃŠ°Š¹Š»Šµ '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1533"/> + <source>File '%s' is neither block device nor regular file</source> + <translation>Š¤Š°Š¹Š» '%s' Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ Š½Šø Š±Š»Š¾ŃŠ½ŃŠ¼ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾Š¼, Š½Šø ŃŠµŠ³ŃŠ»ŃŃŠ½ŃŠ¼ ŃŠ°Š¹Š»Š¾Š¼</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1571"/> + <source>File '%s' is no block or char device</source> + <translation>Š¤Š°Š¹Š» '%s' Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ Š½Šø Š±Š»Š¾ŃŠ½ŃŠ¼ Š½Šø ŃŠøŠ¼Š²Š¾Š»ŃŠ½ŃŠ¼ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾Š¼</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1610"/> + <source>File '%s' is neither character device nor regular file</source> + <translation>Š¤Š°Š¹Š» '%s' Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ Š½Šø ŃŠøŠ¼Š²Š¾Š»ŃŠ½ŃŠ¼ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾Š¼ Š½Šø ŃŠµŠ³ŃŠ»ŃŃŠ½ŃŠ¼ ŃŠ°Š¹Š»Š¾Š¼</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1635"/> + <source>Detected size of raw disk '%s' is %RU64, an invalid value</source> + <translation>ŠŠ±Š½Š°ŃŃŠ¶ŠµŠ½Š½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ raw Š“ŠøŃŠŗŠ° '%s' %RU64, ŃŃŠ¾ Š½Šµ ŃŠ²Š»ŃŠµŃŃŃ Š“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¼ Š·Š½Š°ŃŠµŠ½ŠøŠµŠ¼</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1667"/> + <source>Incorrect value in partitions parameter</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ Š² ŠæŠ°ŃŠ°Š¼ŠµŃŃŠµ partitions</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1681"/> + <source>Incorrect separator in partitions parameter</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠ°Š·Š“ŠµŠ»ŠøŃŠµŠ»Ń Š² ŠæŠ°ŃŠ°Š¼ŠµŃŃŠµ partitions</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1691"/> + <source>Cannot read the partition information from '%s'</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŃŠøŃŠ°ŃŃ ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾ ŃŠ°Š·Š“ŠµŠ»Š°Ń
ŠøŠ· '%s'</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1706"/> + <source>It is not possible (and necessary) to explicitly give access to the extended partition %u. If required, enable access to all logical partitions inside this extended partition.</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ (Šø Š½Šµ Š½ŃŠ¶Š½Š¾) ŃŠ²Š½Š¾ Š“Š°Š²Š°ŃŃ Š“Š¾ŃŃŃŠæ Šŗ ŃŠ°ŃŃŠøŃŠµŠ½Š½Š¾Š¼Ń ŃŠ°Š·Š“ŠµŠ»Ń %u. ŠŃŠ»Šø Š½ŃŠ¶Š½Š¾, Š“Š°Š¹ŃŠµ Š“Š¾ŃŃŃŠæ ŠŗŠ¾ Š²ŃŠµŠ¼ Š»Š¾Š³ŠøŃŠµŃŠŗŠøŠ¼ ŃŠ°Š·Š“ŠµŠ»Š°Š¼ Š²Š½ŃŃŃŠø ŃŠ°ŃŃŠøŃŠµŠ½Š½Š¾Š³Š¾ ŃŠ°Š·Š“ŠµŠ»Š°.</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1726"/> + <location filename="../VBoxInternalManage.cpp" line="1794"/> + <source>Out of memory allocating the partition list for '%s'</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ ŃŠæŠøŃŠ¾Šŗ ŃŠ°Š·Š“ŠµŠ»Š¾Š² Š“Š»Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1742"/> + <source>Out of memory allocating the partition descriptor for '%s'</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ Š“ŠµŃŠŗŃŠøŠæŃŠ¾Ń ŃŠ°Š·Š“ŠµŠ»Š° Š“Š»Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1751"/> + <source>Cannot read partition data from raw device '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŃŠøŃŠ°ŃŃ Š“Š°Š½Š½ŃŠµ ŃŠ°Š·Š“ŠµŠ»Š° ŠøŠ· raw ŃŃŃŠ°ŃŠ¾Š¹ŃŃŠ²Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1763"/> + <source>Cannot open replacement MBR file '%s' specified with -mbr: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ ŃŠ°Š¹Š» Š·Š°Š¼ŠµŠ½Ń MBR '%s', ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠµŃŠµŠ· -mbr: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1771"/> + <source>Cannot read replacement MBR file '%s': %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŃŠøŃŠ°ŃŃ ŃŠ°Š¹Š» Š·Š°Š¼ŠµŠ½Ń MBR '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1837"/> + <source>Cannot create reference to individual partition %u, rc=%Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŃŃŃŠ»ŠŗŃ Š½Š° ŠøŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š“ŠµŠ» %u, rc=%Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1852"/> + <source>Cannot create reference to individual partition %u (numbered %u), rc=%Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŃŃŃŠ»ŠŗŃ Š½Š° ŠøŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š“ŠµŠ» %u (ŠæŃŠ¾Š½ŃŠ¼ŠµŃŠ¾Š²Š°Š½Š½ŃŠ¹ ŠŗŠ°Šŗ %u), rc=%Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1914"/> + <source>MBR/EPT overlaps with data area</source> + <translation>MBR/EPT ŠæŠµŃŠµŠŗŃŃŠ²Š°ŠµŃ Š¾Š±Š»Š°ŃŃŃ Š“Š°Š½Š½ŃŃ
</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1920"/> + <source>GPT overlaps with data area</source> + <translation>GPT ŠæŠµŃŠµŠŗŃŃŠ²Š°ŠµŃ Š¾Š±Š»Š°ŃŃŃ Š“Š°Š½Š½ŃŃ
</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1977"/> + <source>Cannot create the raw disk VMDK: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ VMDK raw Š“ŠøŃŠŗ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1980"/> + <source>RAW host disk access VMDK file %s created successfully. +</source> + <translation>VMDK ŃŠ°Š¹Š» %s Š“Š»Ń Š“Š¾ŃŃŃŠæŠ° Šŗ RAW Š“ŠøŃŠŗŃ Ń
Š¾ŃŃŠ° ŃŠ¾Š·Š“Š°Š½ ŃŃŠæŠµŃŠ½Š¾. +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2002"/> + <source>The raw disk vmdk file was not created</source> + <translation>vmdk ŃŠ°Š¹Š» Šŗ raw Š“ŠøŃŠŗŃ Š½Šµ ŃŠ¾Š·Š“Š°Š½</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2039"/> + <source>Mandatory parameter -from missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ -from</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2041"/> + <source>Mandatory parameter -to missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ -to</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2065"/> + <source>Cannot rename the image: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠµŃŠµŠøŠ¼ŠµŠ½Š¾Š²Š°ŃŃ Š¾Š±ŃŠ°Š·: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2068"/> + <source>Cannot create the source image: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±ŃŠ°Š· ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2112"/> + <source>Mandatory filename parameter missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ ŠøŠ¼Ń ŃŠ°Š¹Š»Š°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2114"/> + <source>Mandatory outputfile parameter missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ: Š²ŃŃ
Š¾Š“Š½Š¾Š¹ ŃŠ°Š¹Š»</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2142"/> + <source>Cannot create destination file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŃŠ°Š¹Š» Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2161"/> + <location filename="../VBoxInternalManage.cpp" line="2304"/> + <location filename="../VBoxInternalManage.cpp" line="2424"/> + <source>No file format specified and autodetect failed - please specify format: %Rrc</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŃŠ¾ŃŠ¼Š°Ń ŃŠ°Š¹Š»Š°, ŃŠ°ŠŗŠ¶Šµ Š°Š²ŃŠ¾Š“ŠµŃŠµŠŗŃ Š½Šµ ŠæŃŠ¾ŃŠµŠ» - ŠæŠ¾Š¶Š°Š»ŃŠ¹ŃŃŠ°, ŃŠŗŠ°Š¶ŠøŃŠµ ŃŠ¾ŃŠ¼Š°Ń: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2164"/> + <source>Only converting harddisk images is supported</source> + <translation>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ ŃŠ¾Š»ŃŠŗŠ¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š¾Š² Š¶ŠµŃŃŠŗŠøŃ
Š“ŠøŃŠŗŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2179"/> + <location filename="../VBoxInternalManage.cpp" line="2323"/> + <source>Cannot open the source image: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ Š¾Š±ŃŠ°Š· ŠøŃŃŠ¾ŃŠ½ŠøŠŗŠ°: %Rrc</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxInternalManage.cpp" line="2189"/> + <source>Converting image "%s" with size %RU64 bytes (%RU64MB) to raw... +</source> + <translation> + <numerusform>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° "%s" ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹Ń (%RU64MB) Š² raw... +</numerusform> + <numerusform>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° "%s" ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹ŃŠ° (%RU64MB) Š² raw... +</numerusform> + <numerusform>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° "%s" ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹Ń (%RU64MB) Š² raw... +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2211"/> + <source>Cannot copy image data: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ¾ŠæŠøŃŠ¾Š²Š°ŃŃ Š“Š°Š½Š½ŃŠµ Š¾Š±ŃŠ°Š·Š°: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2223"/> + <source>Out of memory allocating read buffer</source> + <translation>ŠŠµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø ŠæŠ¾Š“ Š±ŃŃŠµŃ ŃŃŠµŠ½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2280"/> + <location filename="../VBoxInternalManage.cpp" line="2401"/> + <source>Mandatory input image parameter missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ Š²Ń
Š¾Š“Š½Š¾Š¹ Š¾Š±ŃŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2282"/> + <source>Mandatory output image parameter missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ Š²ŃŃ
Š¾Š“Š½Š¾Š¹ Š¾Š±ŃŠ°Š·</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2315"/> + <source>Cannot create the source virtual disk container: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŠŗŠ¾Š½ŃŠµŠ¹Š½ŠµŃ ŠøŃŃ
Š¾Š“Š½Š¾Š³Š¾ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ°: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2334"/> + <source>Cannot create the destination virtual disk container: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ¾Š·Š“Š°ŃŃ ŠŗŠ¾Š½ŃŠµŠ¹Š½ŠµŃ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ° Š½Š°Š·Š½Š°ŃŠµŠ½ŠøŃ: %Rrc</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxInternalManage.cpp" line="2339"/> + <source>Converting image "%s" with size %RU64 bytes (%RU64MB)... +</source> + <translation> + <numerusform>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° "%s" ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹Ń (%RU64MB)... +</numerusform> + <numerusform>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° "%s" ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹ŃŠ° (%RU64MB)... +</numerusform> + <numerusform>ŠŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°Š½ŠøŠµ Š¾Š±ŃŠ°Š·Š° "%s" ŃŠ°Š·Š¼ŠµŃŠ¾Š¼ %RU64 Š±Š°Š¹Ń (%RU64MB)... +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2348"/> + <source>Cannot copy the image: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ¾ŠæŠøŃŠ¾Š²Š°ŃŃ Š¾Š±ŃŠ°Š·: %Rrc</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2476"/> + <location filename="../VBoxInternalManage.cpp" line="2611"/> + <source>Missing VM name/UUID</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ¼Ń ŠŠ/UUID</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2576"/> + <source>One or more of the requested features are not implemented! Feel free to do this.</source> + <translation>ŠŠ“ŠøŠ½ ŠøŠ»Šø Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ Š·Š°ŠæŃŠ¾ŃŠµŠ½Š½ŃŃ
ŃŃŠ½ŠŗŃŠøŠ¹ Š½Šµ ŃŠµŠ°Š»ŠøŠ·Š¾Š²Š°Š½Ń! ŠŠµ ŃŃŠµŃŠ½ŃŠ¹ŃŠµŃŃ ŃŠ“ŠµŠ»Š°ŃŃ ŠøŃ
.</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2592"/> + <source>password to hash required</source> + <translation>ŃŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ¾Š»Ń Š“Š»Ń Ń
ŠµŃŠ°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2598"/> + <source>Password hash: %s +</source> + <translation>Š„ŠµŃ ŠæŠ°ŃŠ¾Š»Ń: %s +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2641"/> + <source>Invalid update interval specified</source> + <translation>Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½ŃŠµŃŠ²Š°Š» Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŃ</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2643"/> + <source>argc=%d interval=%u +</source> + <translation>argc=%d ŠøŠ½ŃŠµŃŠ²Š°Š»=%u +</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2694"/> + <source>Command missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠŗŠ¾Š¼Š°Š½Š“Š°</translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2734"/> + <source>Invalid command '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠŗŠ¾Š¼Š°Š½Š“Š° '%s'</translation> + </message> +</context> +<context> + <name>List</name> + <message> + <location filename="../VBoxManageList.cpp" line="54"/> + <location filename="../VBoxManageList.cpp" line="68"/> + <location filename="../VBoxManageList.cpp" line="94"/> + <location filename="../VBoxManageList.cpp" line="853"/> + <location filename="../VBoxManageList.cpp" line="864"/> + <source>Unknown</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="59"/> + <location filename="../VBoxManageList.cpp" line="73"/> + <source>unknown</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="66"/> + <source>Up</source> + <translation>ŠŠŗŠ»ŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="67"/> + <source>Down</source> + <translation>ŠŃŠŗŠ»ŃŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="81"/> + <source>HardDisk</source> + <translation>ŠŠµŃŃŠŗŠøŠ¹ ŠŠøŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="83"/> + <source>Floppy</source> + <translation>Š¤Š»Š¾ŠæŠæŠø</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="86"/> + <source>Network</source> + <translation>Š”ŠµŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="88"/> + <source>SharedFolder</source> + <translation>ŠŠ±ŃŠ°Ń ŠæŠ°ŠæŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="89"/> + <source>Graphics3D</source> + <translation>3D Š³ŃŠ°ŃŠøŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="111"/> + <location filename="../VBoxManageList.cpp" line="149"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="156"/> + <location filename="../VBoxManageList.cpp" line="215"/> + <location filename="../VBoxManageList.cpp" line="261"/> + <location filename="../VBoxManageList.cpp" line="1340"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="162"/> + <location filename="../VBoxManageList.cpp" line="221"/> + <location filename="../VBoxManageList.cpp" line="267"/> + <source>Enabled</source> + <translation>ŠŠŗŠ»ŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="162"/> + <location filename="../VBoxManageList.cpp" line="221"/> + <location filename="../VBoxManageList.cpp" line="267"/> + <source>Disabled</source> + <translation>ŠŃŠŗŠ»ŃŃŠµŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="166"/> + <source>IPAddress: %ls +</source> + <translation>IP Š°Š“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="169"/> + <location filename="../VBoxManageList.cpp" line="225"/> + <source>NetworkMask: %ls +</source> + <translation>Š”ŠµŃŠµŠ²Š°Ń Š¼Š°ŃŠŗŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="172"/> + <source>IPV6Address: %ls +</source> + <translation>IPV6 Š°Š“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="175"/> + <source>IPV6NetworkMaskPrefixLength: %d +</source> + <translation>ŠŠ»ŠøŠ½Š° ŠæŃŠµŃŠøŠŗŃŠ° ŃŠµŃŠµŠ²Š¾Š¹ Š¼Š°ŃŠŗŠø IPV6: %d +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="178"/> + <source>HardwareAddress: %ls +</source> + <translation>ŠŠæŠæŠ°ŃŠ°ŃŠ½ŃŠ¹ Š°Š“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="181"/> + <source>MediumType: %s +</source> + <translation>Š¢ŠøŠæ Š½Š¾ŃŠøŃŠµŠ»Ń: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="184"/> + <source>Wireless: %s +</source> + <translation>ŠŠµŃŠæŃŠ¾Š²Š¾Š“Š½ŃŠ¹: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="184"/> + <location filename="../VBoxManageList.cpp" line="1069"/> + <source>Yes</source> + <translation>ŠŠ°</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="184"/> + <location filename="../VBoxManageList.cpp" line="1069"/> + <source>No</source> + <translation>ŠŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="187"/> + <source>Status: %s +</source> + <translation>Š”ŃŠ°ŃŃŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="190"/> + <location filename="../VBoxManageList.cpp" line="236"/> + <location filename="../VBoxManageList.cpp" line="279"/> + <source>VBoxNetworkName: %ls + +</source> + <translation>ŠŠ¼Ń ŃŠµŃŠø VBox: %ls + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="221"/> + <location filename="../VBoxManageList.cpp" line="267"/> + <source>State: %s +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="228"/> + <source>LowerIP: %ls +</source> + <translation>ŠŠøŠ¶Š½ŠøŠ¹ IP: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="231"/> + <source>UpperIP: %ls +</source> + <translation>ŠŠµŃŃ
Š½ŠøŠ¹ IP: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="271"/> + <source>CloudProvider: %ls +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="274"/> + <source>CloudProfile: %ls +</source> + <translation>ŠŠ±Š»Š°ŃŠ½ŃŠ¹ ŠæŃŠ¾ŃŠøŠ»Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="277"/> + <source>CloudNetworkId: %ls +</source> + <translation>ID Š¾Š±Š»Š°ŃŠ½Š¾Š¹ ŃŠµŃŠø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="301"/> + <source>HW virtualization</source> + <translation>ŠŠæŠæŠ°ŃŠ°ŃŠ½Š°Ń Š²ŠøŃŃŃŠ°Š»ŠøŠ·Š°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="303"/> + <source>long mode</source> + <translation>Š“Š»ŠøŠ½Š½ŃŠ¹ ŃŠµŠ¶ŠøŠ¼</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="304"/> + <source>nested paging</source> + <translation>Š²Š»Š¾Š¶ŠµŠ½Š½ŃŠµ ŃŃŃŠ°Š½ŠøŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="305"/> + <source>unrestricted guest</source> + <translation>Š½ŠµŠ¾Š³ŃŠ°Š½ŠøŃŠµŠ½Š½ŃŠ¹ Š³Š¾ŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="306"/> + <source>nested HW virtualization</source> + <translation>Š²Š»Š¾Š¶ŠµŠ½Š½Š°Ń Š°ŠæŠæŠ°ŃŠ°ŃŠ½Š°Ń Š²ŠøŃŃŃŠ°Š»ŠøŠ·Š°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="307"/> + <source>virt. vmsave/vmload</source> + <translation>virt. vmsave/vmload</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="313"/> + <source>Host Information: + +</source> + <translation>ŠŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾ Ń
Š¾ŃŃŠµ: + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="319"/> + <source>Host time: %s +</source> + <translation>ŠŃŠµŠ¼Ń Ń
Š¾ŃŃŠ°: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="323"/> + <source>Processor online count: %lu +</source> + <translation>Š§ŠøŃŠ»Š¾ Š°ŠŗŃŠøŠ²Š½ŃŃ
ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ¾Š²: %lu +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="326"/> + <source>Processor count: %lu +</source> + <translation>Š§ŠøŃŠ»Š¾ ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ¾Š²: %lu +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="329"/> + <source>Processor online core count: %lu +</source> + <translation>Š§ŠøŃŠ»Š¾ Š°ŠŗŃŠøŠ²Š½ŃŃ
ŃŠ“ŠµŃ ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ¾Š²: %lu +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="332"/> + <source>Processor core count: %lu +</source> + <translation>Š§ŠøŃŠ»Š¾ ŃŠ“ŠµŃ ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ¾Š²: %lu +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="337"/> + <source>Processor supports %s: %s +</source> + <translation>ŠŃŠ¾ŃŠµŃŃŠ¾Ń ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃ %s: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="337"/> + <location filename="../VBoxManageList.cpp" line="671"/> + <location filename="../VBoxManageList.cpp" line="825"/> + <location filename="../VBoxManageList.cpp" line="889"/> + <location filename="../VBoxManageList.cpp" line="1803"/> + <location filename="../VBoxManageList.cpp" line="1808"/> + <source>yes</source> + <translation>Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="337"/> + <location filename="../VBoxManageList.cpp" line="671"/> + <location filename="../VBoxManageList.cpp" line="825"/> + <location filename="../VBoxManageList.cpp" line="889"/> + <location filename="../VBoxManageList.cpp" line="1803"/> + <location filename="../VBoxManageList.cpp" line="1808"/> + <source>no</source> + <translation>Š½ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="344"/> + <source>Processor#%u speed: %lu MHz +</source> + <translation>Š”ŠŗŠ¾ŃŠ¾ŃŃŃ ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ° #%u: %lu ŠŠŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="346"/> + <source>Processor#%u speed: unknown +</source> + <translation>Š”ŠŗŠ¾ŃŠ¾ŃŃŃ ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ° #%u: Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="349"/> + <source>Processor#%u description: %ls +</source> + <translation>ŠŠæŠøŃŠ°Š½ŠøŠµ ŠæŃŠ¾ŃŠµŃŃŠ¾ŃŠ° #%u: %ls +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="354"/> + <source>Memory size: %lu MByte +</source> + <translation> + <numerusform>Š Š°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø: %lu ŠŠŠ°Š¹Ń +</numerusform> + <numerusform>Š Š°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø: %lu ŠŠŠ°Š¹ŃŠ° +</numerusform> + <numerusform>Š Š°Š·Š¼ŠµŃ ŠæŠ°Š¼ŃŃŠø: %lu ŠŠŠ°Š¹Ń +</numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="358"/> + <source>Memory available: %lu MByte +</source> + <translation> + <numerusform>ŠŠ¾ŃŃŃŠæŠ½Š¾ ŠæŠ°Š¼ŃŃŠø: %lu ŠŠŠ°Š¹Ń +</numerusform> + <numerusform>ŠŠ¾ŃŃŃŠæŠ½Š¾ ŠæŠ°Š¼ŃŃŠø: %lu ŠŠŠ°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠ¾ŃŃŃŠæŠ½Š¾ ŠæŠ°Š¼ŃŃŠø: %lu ŠŠŠ°Š¹Ń +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="362"/> + <source>Operating system: %ls +</source> + <translation>ŠŠæŠµŃŠ°ŃŠøŠ¾Š½Š½Š°Ń ŃŠøŃŃŠµŠ¼Š°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="366"/> + <source>Operating system version: %ls +</source> + <translation>ŠŠµŃŃŠøŃ Š¾ŠæŠµŃŠ°ŃŠøŠ¾Š½Š½Š¾Š¹ ŃŠøŃŃŠµŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="424"/> + <source>Supported hard disk backends: + +</source> + <translation>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠµ Š±ŃŠŗŠµŠ½Š“Ń Š¶ŠµŃŃŠŗŠøŃ
Š“ŠøŃŠŗŠ¾Š²: + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="443"/> + <source>Backend %u: id='%ls' description='%ls' capabilities=%#06x extensions='</source> + <translation>ŠŃŠŗŠµŠ½Š“ %u: id='%ls' Š¾ŠæŠøŃŠ°Š½ŠøŠµ='%ls' Š²Š¾Š·Š¼Š¾Š¶Š½Š¾ŃŃŠø=%#06x ŃŠ°ŃŃŠøŃŠµŠ½ŠøŃ='</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="472"/> + <source> properties=(</source> + <translation> ŃŠ²Š¾Š¹ŃŃŠ²Š°=(</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="477"/> + <source> + name='%ls' desc='%ls' type=</source> + <translation> + ŠøŠ¼Ń='%ls' Š¾ŠæŠøŃŠ°Š½ŠøŠµ='%ls' ŃŠøŠæ=</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="481"/> + <source>int</source> + <translation>int</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="482"/> + <source>byte</source> + <translation>byte</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="483"/> + <source>string</source> + <translation>string</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="488"/> + <source> flags=%#04x</source> + <translation> ŃŠ»Š°Š³Šø=%#04x</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="489"/> + <source> default='%ls'</source> + <translation> ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ='%ls'</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="515"/> + <source>Host USB Devices: + +</source> + <translation>USB ŃŃŃŃŠ¾Š¹ŃŃŠ²Š° Ń
Š¾ŃŃŠ°: + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="519"/> + <location filename="../VBoxManageList.cpp" line="657"/> + <source><none> + +</source> + <translation><Š½ŠµŃ> + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="543"/> + <source>UUID: %s +VendorId: %#06x (%04X) +ProductId: %#06x (%04X) +Revision: %u.%u (%02u%02u) +Port: %u +</source> + <translation>UUID: %s +ID ŠŠ¾ŃŃŠ°Š²ŃŠøŠŗŠ°: %#06x (%04X) +ID ŠŃŠ¾Š“ŃŠŗŃŠ°: %#06x (%04X) +Š ŠµŠ²ŠøŠ·ŠøŃ: %u.%u (%02u%02u) +ŠŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="559"/> + <source>Low</source> + <translation>ŠŠøŠ·ŠŗŠ°Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="562"/> + <source>Full</source> + <translation>ŠŠ¾Š»Š½Š°Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="565"/> + <source>High</source> + <translation>ŠŃŃŠ¾ŠŗŠ°Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="568"/> + <source>Super</source> + <translation>Š”ŃŠæŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="571"/> + <source>SuperPlus</source> + <translation>Š”ŃŠæŠµŃŠŠ»ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="578"/> + <source>USB version/speed: %u/%s +</source> + <translation>ŠŠµŃŃŠøŃ/ŃŠŗŠ¾ŃŠ¾ŃŃŃ USB: %u/%s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="587"/> + <source>Manufacturer: %ls +</source> + <translation>ŠŃŠ¾ŠøŠ·Š²Š¾Š“ŠøŃŠµŠ»Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="591"/> + <source>Product: %ls +</source> + <translation>ŠŃŠ¾Š“ŃŠŗŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="594"/> + <source>SerialNumber: %ls +</source> + <translation>Š”ŠµŃŠøŠ¹Š½ŃŠ¹ Š½Š¾Š¼ŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="597"/> + <source>Address: %ls +</source> + <translation>ŠŠ“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="600"/> + <source>Port path: %ls +</source> + <translation>ŠŃŃŃ Šŗ ŠæŠ¾ŃŃŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="609"/> + <source>Not supported</source> + <translation>ŠŠµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="612"/> + <source>Unavailable</source> + <translation>ŠŠµŠ“Š¾ŃŃŃŠæŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="615"/> + <source>Busy</source> + <translation>ŠŠ°Š½ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="618"/> + <source>Available</source> + <translation>ŠŠ¾ŃŃŃŠæŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="621"/> + <source>Held</source> + <translation>Š£Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="624"/> + <source>Captured</source> + <translation>ŠŠ°Ń
Š²Š°ŃŠµŠ½</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="630"/> + <source>Current State: %s + +</source> + <translation>Š¢ŠµŠŗŃŃŠµŠµ ŃŠ¾ŃŃŠ¾ŃŠ½ŠøŠµ: %s + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="647"/> + <source>Global USB Device Filters: + +</source> + <translation>ŠŠ»Š¾Š±Š°Š»ŃŠ½ŃŠµ ŃŠøŠ»ŃŃŃŃ USB ŃŃŃŃŠ¾Š¹ŃŃŠ²: + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="667"/> + <source>Index: %zu +</source> + <translation>ŠŠ½Š“ŠµŠŗŃ: %zu +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="671"/> + <source>Active: %s +</source> + <translation>ŠŠŗŃŠøŠ²Š½Š¾: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="675"/> + <source><invalid></source> + <translation><Š½ŠµŠ“ŠµŠ¹ŃŃŠ²ŠøŃŠµŠ»ŃŠ½Š¾></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="679"/> + <source>Ignore</source> + <translation>ŠŠ³Š½Š¾ŃŠøŃŠ¾Š²Š°ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="682"/> + <source>Hold</source> + <translation>Š£Š“ŠµŃŠ¶ŠøŠ²Š°ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="687"/> + <source>Action: %s +</source> + <translation>ŠŠµŠ¹ŃŃŠ²ŠøŠµ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="691"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="693"/> + <source>VendorId: %ls +</source> + <translation>ID ŠŠ¾ŃŃŠ°Š²ŃŠøŠŗŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="695"/> + <source>ProductId: %ls +</source> + <translation>ID ŠŃŠ¾Š“ŃŠŗŃŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="697"/> + <source>Revision: %ls +</source> + <translation>Š ŠµŠ²ŠøŠ·ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="699"/> + <source>Manufacturer: %ls +</source> + <translation>ŠŃŠ¾ŠøŠ·Š²Š¾Š“ŠøŃŠµŠ»Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="701"/> + <source>Product: %ls +</source> + <translation>ŠŃŠ¾Š“ŃŠŗŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="703"/> + <source>Serial Number: %ls + +</source> + <translation>Š”ŠµŃŠøŠ¹Š½ŃŠ¹ Š½Š¾Š¼ŠµŃ: %ls + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="728"/> + <source>API version: %ls +</source> + <translation>ŠŠµŃŃŠøŃ API: %ls +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="731"/> + <source>Minimum guest RAM size: %u Megabytes +</source> + <translation> + <numerusform>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + <numerusform>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="733"/> + <source>Maximum guest RAM size: %u Megabytes +</source> + <translation> + <numerusform>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + <numerusform>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š³Š¾ŃŃŠµŠ²Š¾Š¹ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="735"/> + <source>Minimum video RAM size: %u Megabytes +</source> + <translation> + <numerusform>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š²ŠøŠ“ŠµŠ¾ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + <numerusform>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š²ŠøŠ“ŠµŠ¾ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š²ŠøŠ“ŠµŠ¾ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="737"/> + <source>Maximum video RAM size: %u Megabytes +</source> + <translation> + <numerusform>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š²ŠøŠ“ŠµŠ¾ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + <numerusform>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š²ŠøŠ“ŠµŠ¾ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½ŃŠ¹ ŃŠ°Š·Š¼ŠµŃ Š²ŠøŠ“ŠµŠ¾ RAM: %u ŠŠµŠ³Š°Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="739"/> + <source>Maximum guest monitor count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
Š¼Š¾Š½ŠøŃŠ¾ŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="741"/> + <source>Minimum guest CPU count: %u +</source> + <translation>ŠŠøŠ½ŠøŠ¼Š°Š»ŃŠ½Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
Š¦ŠŠ£: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="743"/> + <source>Maximum guest CPU count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ Š³Š¾ŃŃŠµŠ²ŃŃ
Š¦ŠŠ£: %u +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="745"/> + <source>Virtual disk limit (info): %lld Bytes +</source> + <translation> + <numerusform>ŠŠ³ŃŠ°Š½ŠøŃŠµŠ½ŠøŠµ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ° (ŠøŠ½ŃŠ¾): %lld ŠŠ°Š¹Ń +</numerusform> + <numerusform>ŠŠ³ŃŠ°Š½ŠøŃŠµŠ½ŠøŠµ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ° (ŠøŠ½ŃŠ¾): %lld ŠŠ°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠ³ŃŠ°Š½ŠøŃŠµŠ½ŠøŠµ Š²ŠøŃŃŃŠ°Š»ŃŠ½Š¾Š³Š¾ Š“ŠøŃŠŗŠ° (ŠøŠ½ŃŠ¾): %lld ŠŠ°Š¹Ń +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="747"/> + <source>Maximum Serial Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŠæŠ¾ŃŠ»ŠµŠ“Š¾Š²Š°ŃŠµŠ»ŃŠ½ŃŃ
ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="749"/> + <source>Maximum Parallel Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŠæŠ°ŃŠ°Š»Š»ŠµŠ»ŃŠ½ŃŃ
ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="751"/> + <source>Maximum Boot Position: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š°Ń Š·Š°Š³ŃŃŠ·Š¾ŃŠ½Š°Ń ŠæŠ¾Š·ŠøŃŠøŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="753"/> + <source>Maximum PIIX3 Network Adapter count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 ŃŠµŃŠµŠ²ŃŃ
Š°Š“Š°ŠæŃŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="755"/> + <source>Maximum ICH9 Network Adapter count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 ŃŠµŃŠµŠ²ŃŃ
Š°Š“Š°ŠæŃŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="757"/> + <source>Maximum PIIX3 IDE Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 IDE ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="759"/> + <source>Maximum ICH9 IDE Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 IDE ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="761"/> + <source>Maximum IDE Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ IDE ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="763"/> + <source>Maximum Devices per IDE Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° IDE ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="765"/> + <source>Maximum PIIX3 SATA Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 SATA ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="767"/> + <source>Maximum ICH9 SATA Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 SATA ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="769"/> + <source>Maximum SATA Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ SATA ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="771"/> + <source>Maximum Devices per SATA Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° SATA ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="773"/> + <source>Maximum PIIX3 SCSI Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 SCSI ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="775"/> + <source>Maximum ICH9 SCSI Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 SCSI ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="777"/> + <source>Maximum SCSI Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ SCSI ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="779"/> + <source>Maximum Devices per SCSI Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° SCSI ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="781"/> + <source>Maximum SAS PIIX3 Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 SAS ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="783"/> + <source>Maximum SAS ICH9 Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 SAS ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="785"/> + <source>Maximum SAS Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ SAS ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="787"/> + <source>Maximum Devices per SAS Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° SAS ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="789"/> + <source>Maximum NVMe PIIX3 Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 NVMe ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="791"/> + <source>Maximum NVMe ICH9 Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 NVMe ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="793"/> + <source>Maximum NVMe Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ NVMe ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="795"/> + <source>Maximum Devices per NVMe Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° NVMe ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="797"/> + <source>Maximum virtio-scsi PIIX3 Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 virtio-scsi ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="799"/> + <source>Maximum virtio-scsi ICH9 Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 virtio-scsi ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="801"/> + <source>Maximum virtio-scsi Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ virtio-scsi ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="803"/> + <source>Maximum Devices per virtio-scsi Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° virtio-scsi ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="805"/> + <source>Maximum PIIX3 Floppy Controllers:%u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ PIIX3 Š¤Š»Š¾ŠæŠæŠø ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="807"/> + <source>Maximum ICH9 Floppy Controllers: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ICH9 Š¤Š»Š¾ŠæŠæŠø ŠŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="809"/> + <source>Maximum Floppy Port count: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ Š¤Š»Š¾ŠæŠæŠø ŠæŠ¾ŃŃŠ¾Š²: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="811"/> + <source>Maximum Devices per Floppy Port: %u +</source> + <translation>ŠŠ°ŠŗŃŠøŠ¼Š°Š»ŃŠ½Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ² Š½Š° Š¤Š»Š¾ŠæŠæŠø ŠæŠ¾ŃŃ: %u +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="814"/> + <source>Free disk space warning at: %u Bytes +</source> + <translation> + <numerusform>ŠŠ°ŃŃ ŠæŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u Š±Š°Š¹Ń +</numerusform> + <numerusform>ŠŠ°ŃŃ ŠæŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠ°ŃŃ ŠæŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="816"/> + <source>Free disk space warning at: %u %% +</source> + <translation>ŠŠ°ŃŃ ŠæŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u %% +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="818"/> + <source>Free disk space error at: %u Bytes +</source> + <translation> + <numerusform>ŠŠ°ŃŃ Š¾ŃŠøŠ±ŠŗŃ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u Š±Š°Š¹Ń +</numerusform> + <numerusform>ŠŠ°ŃŃ Š¾ŃŠøŠ±ŠŗŃ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>ŠŠ°ŃŃ Š¾ŃŠøŠ±ŠŗŃ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="820"/> + <source>Free disk space error at: %u %% +</source> + <translation>ŠŠ°ŃŃ Š¾ŃŠøŠ±ŠŗŃ ŠŗŠ¾Š³Š“Š° Š½Š° Š“ŠøŃŠŗŠµ Š¾ŃŃŠ°Š»Š¾ŃŃ ŃŠ²Š¾Š±Š¾Š“Š½Š¾: %u %% +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="823"/> + <source>Default machine folder: %ls +</source> + <translation>ŠŠ°ŠæŠŗŠ° Š¼Š°ŃŠøŠ½Ń ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="825"/> + <source>Raw-mode Supported: %s +</source> + <translation>Raw-ŃŠµŠ¶ŠøŠ¼ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="827"/> + <source>Exclusive HW virtualization use: %s +</source> + <translation>ŠŠŗŃŠŗŠ»ŃŠ·ŠøŠ²Š½Š¾Šµ ŠøŃŠæŠ¾Š»ŃŠ·Š¾Š²Š°Š½ŠøŠµ Š°ŠæŠæŠ°ŃŠ°ŃŠ½Š¾Š¹ Š²ŠøŃŃŃŠ°Š»ŠøŠ·Š°ŃŠøŠø: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="827"/> + <location filename="../VBoxManageList.cpp" line="1867"/> + <location filename="../VBoxManageList.cpp" line="1871"/> + <source>on</source> + <translation>Š²ŠŗŠ»</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="827"/> + <location filename="../VBoxManageList.cpp" line="1867"/> + <location filename="../VBoxManageList.cpp" line="1871"/> + <source>off</source> + <translation>Š²ŃŠŗŠ»</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="829"/> + <source>Default hard disk format: %ls +</source> + <translation>Š¤Š¾ŃŠ¼Š°Ń Š¶ŠµŃŃŠŗŠ¾Š³Š¾ Š“ŠøŃŠŗŠ° ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="831"/> + <source>VRDE auth library: %ls +</source> + <translation>ŠŠøŠ±Š»ŠøŠ¾ŃŠµŠŗŠ° Š°ŃŃŠµŠ½ŃŠøŃŠøŠŗŠ°ŃŠøŠø VRDE: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="833"/> + <source>Webservice auth. library: %ls +</source> + <translation>ŠŠøŠ±Š»ŠøŠ¾ŃŠµŠŗŠ° Š°ŃŃŠµŠ½ŃŠøŃŠøŠŗŠ°ŃŠøŠø Š²ŠµŠ±ŃŠµŃŠ²ŠøŃŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="835"/> + <source>Remote desktop ExtPack: %ls +</source> + <translation>ŠŠ°ŠŗŠµŃ ŃŠ°ŃŃŠøŃŠµŠ½ŠøŃ ŃŠ“Š°Š»ŠµŠ½Š½Š¾Š³Š¾ ŃŠ°Š±Š¾ŃŠµŠ³Š¾ ŃŃŠ¾Š»Š°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="837"/> + <source>Log history count: %u +</source> + <translation>Š Š°Š·Š¼ŠµŃ ŠøŃŃŠ¾ŃŠøŠø Š² Š¶ŃŃŠ½Š°Š»Šµ: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="839"/> + <source>Default frontend: %ls +</source> + <translation>Š¤ŃŠ¾Š½ŃŃŠ½Š“ ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="844"/> + <source>Null</source> + <translation>ŠŃŃŃŠ¾</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="855"/> + <source>Default audio driver: %s +</source> + <translation>ŠŃŠ“ŠøŠ¾ Š“ŃŠ°Š¹Š²ŠµŃ ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="857"/> + <source>Autostart database path: %ls +</source> + <translation>ŠŃŃŃ Š±Š°Š·Ń Š“Š°Š½Š½ŃŃ
Š°Š²ŃŠ¾ŃŃŠ°ŃŃŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="859"/> + <source>Default Guest Additions ISO: %ls +</source> + <translation>ISO ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="861"/> + <source>Logging Level: %ls +</source> + <translation>Š£ŃŠ¾Š²ŠµŠ½Ń Š¶ŃŃŠ½Š°Š»Š°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="867"/> + <source>System</source> + <translation>Š”ŠøŃŃŠµŠ¼Š°</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="868"/> + <source>NoProxy</source> + <translation>ŠŠµŠ· ŠŃŠ¾ŠŗŃŠø</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="869"/> + <source>Manual</source> + <translation>ŠŃŃŃŠ½ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="874"/> + <source>Proxy Mode: %s +</source> + <translation>Š ŠµŠ¶ŠøŠ¼ ŠŃŠ¾ŠŗŃŠø: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="876"/> + <source>Proxy URL: %ls +</source> + <translation>URL ŠŃŠ¾ŠŗŃŠø: %ls +</translation> + </message> + <message> + <source>Update check enabled: %s +</source> + <translation type="vanished">ŠŃŠ¾Š²ŠµŃŠŗŠ° Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹ Š²ŠŗŠ»ŃŃŠµŠ½Š°: %s +</translation> + </message> + <message> + <source>Update check count: %u +</source> + <translation type="vanished">ŠŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ ŠæŃŠ¾Š²ŠµŃŠ¾Šŗ Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: %u +</translation> + </message> + <message> + <source>Update check frequency: never +</source> + <translation type="vanished">Š§Š°ŃŃŠ¾ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: Š½ŠøŠŗŠ¾Š³Š“Š° +</translation> + </message> + <message> + <source>Update check frequency: every day +</source> + <translation type="vanished">Š§Š°ŃŃŠ¾ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: ŠŗŠ°Š¶Š“ŃŠ¹ Š“ŠµŠ½Ń +</translation> + </message> + <message numerus="yes"> + <source>Update check frequency: every %u days +</source> + <translation type="vanished"> + <numerusform>Š§Š°ŃŃŠ¾ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: ŠŗŠ°Š¶Š“ŃŠ¹ %u Š“ŠµŠ½Ń +</numerusform> + <numerusform>Š§Š°ŃŃŠ¾ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: ŠŗŠ°Š¶Š“ŃŠµ %u Š“Š½Ń +</numerusform> + <numerusform>Š§Š°ŃŃŠ¾ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: ŠŗŠ°Š¶Š“ŃŠµ %u Š“Š½ŠµŠ¹ +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="908"/> + <source>Stable: new minor and maintenance releases</source> + <translation>Š”ŃŠ°Š±ŠøŠ»ŃŠ½ŃŠµ: Š½Š¾Š²ŃŠµ Š¼ŠøŠ½Š¾ŃŠ½ŃŠµ Šø ŠŗŠ¾ŃŃŠµŠŗŃŠøŃŃŃŃŠøŠµ ŃŠµŠ»ŠøŠ·Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="911"/> + <source>All releases: new minor, maintenance, and major releases</source> + <translation>ŠŃŠµ ŃŠµŠ»ŠøŠ·Ń: Š½Š¾Š²ŃŠµ Š¼ŠøŠ½Š¾ŃŠ½ŃŠµ, ŠŗŠ¾ŃŃŠµŠŗŃŠøŃŃŃŃŠøŠµ Šø Š¼Š°Š¶Š¾ŃŠ½ŃŠµ ŃŠµŠ»ŠøŠ·Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="914"/> + <source>With Betas: new minor, maintenance, major, and beta releases</source> + <translation>Š” Š±ŠµŃŠ°Š¼Šø: Š½Š¾Š²ŃŠµ Š¼ŠøŠ½Š¾ŃŠ½ŃŠµ, ŠŗŠ¾ŃŃŠµŠŗŃŠøŃŃŃŃŠøŠµ, Š¼Š°Š¶Š¾ŃŠ½ŃŠµ Šø Š±ŠµŃŠ° ŃŠµŠ»ŠøŠ·Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="917"/> + <source>Unset</source> + <translation>ŠŠµ Š·Š°Š“Š°Š½Š¾</translation> + </message> + <message> + <source>Update check target: %s +</source> + <translation type="vanished">Š¦ŠµŠ»Ń ŠæŃŠ¾Š²ŠµŃŠŗŠø Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="924"/> + <source>Last check date: %ls +</source> + <translation>ŠŠ¾ŃŠ»ŠµŠ“Š½ŃŃ Š“Š°ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="879"/> + <source>User language: %ls +</source> + <translation>ŠŠ¾Š»ŃŠ·Š¾Š²Š°ŃŠµŠ»ŃŃŠŗŠøŠ¹ ŃŠ·ŃŠŗ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="889"/> + <source>Enabled: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="892"/> + <source>Check count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="895"/> + <source>Check frequency: never +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="897"/> + <source>Check frequency: every day +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="899"/> + <source>Check frequency: every %u days +</source> + <translation type="unfinished"> + <numerusform></numerusform> + <numerusform></numerusform> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="920"/> + <source>Channel: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="922"/> + <source>Repository: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="952"/> + <source> minLeaseTime: default +</source> + <translation> Š¼ŠøŠ½. Š²ŃŠµŠ¼Ń Š°ŃŠµŠ½Š“Ń: ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="954"/> + <source> minLeaseTime: %u sec +</source> + <translation> Š¼ŠøŠ½. Š²ŃŠµŠ¼Ń Š°ŃŠµŠ½Š“Ń: %u ŃŠµŠŗ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="959"/> + <source> defaultLeaseTime: default +</source> + <translation> Š²ŃŠµŠ¼Ń Š°ŃŠµŠ½Š“Ń ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="961"/> + <source> defaultLeaseTime: %u sec +</source> + <translation> Š²ŃŠµŠ¼Ń Š°ŃŠµŠ½Š“Ń ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %u ŃŠµŠŗ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="966"/> + <source> maxLeaseTime: default +</source> + <translation> Š¼Š°ŠŗŃ. Š²ŃŠµŠ¼Ń Š°ŃŠµŠ½Š“Ń: ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="968"/> + <source> maxLeaseTime: %u sec +</source> + <translation> Š¼Š°ŠŗŃ. Š²ŃŠµŠ¼Ń Š°ŃŠµŠ½Š“Ń: %u ŃŠµŠŗ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="974"/> + <source> Forced options: %Rhrc +</source> + <translation> Š¤Š¾ŃŃŠøŃŠ¾Š²Š°Š½Š½ŃŠµ Š¾ŠæŃŠøŠø: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="976"/> + <source> Forced options: None +</source> + <translation> Š¤Š¾ŃŃŠøŃŠ¾Š²Š°Š½Š½ŃŠµ Š¾ŠæŃŠøŠø: ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="979"/> + <source> Forced options: </source> + <translation> Š¤Š¾ŃŃŠøŃŠ¾Š²Š°Š½Š½ŃŠµ Š¾ŠæŃŠøŠø: </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="987"/> + <source> Suppressed opt.s: %Rhrc +</source> + <translation> ŠŠ¾Š“Š°Š²Š»ŠµŠ½Š½ŃŠµ Š¾ŠæŃŠøŠø: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="989"/> + <source> Suppressed opts.: None +</source> + <translation> ŠŠ¾Š“Š°Š²Š»ŠµŠ½Š½ŃŠµ Š¾ŠæŃŠøŠø: ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="992"/> + <source> Suppressed opts.: </source> + <translation> ŠŠ¾Š“Š°Š²Š»ŠµŠ½Š½ŃŠµ Š¾ŠæŃŠøŠø: </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1004"/> + <source> DHCP options: %Rhrc +</source> + <translation> DHCP Š¾ŠæŃŠøŠø: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1007"/> + <source> DHCP options: Return count mismatch: %zu, %zu, %zu +</source> + <translation> DHCP Š¾ŠæŃŠøŠø: Š§ŠøŃŠ»Š¾ Š²Š¾Š·Š²ŃŠ°ŃŠµŠ½Š½ŃŃ
Š½Šµ ŃŠ¾Š¾ŃŠ²ŠµŃŃŃŠ²ŃŠµŃ: %zu, %zu, %zu +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1012"/> + <source> DHCP options: None +</source> + <translation> DHCP Š¾ŠæŃŠøŠø: ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1019"/> + <source> %3d/legacy: %ls +</source> + <translation> %3d/ŃŃŃŠ°ŃŠµŠ²ŃŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1053"/> + <source>NetworkName: %ls +</source> + <translation>ŠŠ¼Ń ŃŠµŃŠø: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1059"/> + <source>LowerIPAddress: %ls +</source> + <translation>ŠŠøŠ¶Š½ŠøŠ¹ IP Š°Š“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1062"/> + <source>UpperIPAddress: %ls +</source> + <translation>ŠŠµŃŃ
Š½ŠøŠ¹ IP Š°Š“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1065"/> + <source>NetworkMask: %ls +</source> + <translation>Š”ŠµŃŠµŠ²Š°Ń Š¼Š°ŃŠŗŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1069"/> + <source>Enabled: %s +</source> + <translation>ŠŠŗŠ»ŃŃŠµŠ½Š¾: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1072"/> + <source>Global Configuration: +</source> + <translation>ŠŠ»Š¾Š±Š°Š»ŃŠ½Š°Ń ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ: +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1087"/> + <source>Groups: %Rrc +</source> + <translation>ŠŃŃŠæŠæŃ: %Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1089"/> + <source>Groups: None +</source> + <translation>ŠŃŃŠæŠæŃ: ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1095"/> + <source>Group: %ls +</source> + <translation>ŠŃŃŠæŠæŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1100"/> + <source> Conditions: %Rhrc +</source> + <translation> Š£ŃŠ»Š¾Š²ŠøŃ: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1102"/> + <source> Conditions: None +</source> + <translation> Š£ŃŠ»Š¾Š²ŠøŃ: ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1112"/> + <source> Conditions: %s %s %ls +</source> + <translation> Š£ŃŠ»Š¾Š²ŠøŃ: %s %s %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1113"/> + <source>include</source> + <translation>Š²ŠŗŠ»ŃŃŠ°Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1113"/> + <source>exclude</source> + <translation>ŠøŃŠŗŠ»ŃŃŠ°Ń</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1135"/> + <source>Individual Configs: %Rrc +</source> + <translation>ŠŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½ŃŠµ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø: %Rrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1137"/> + <source>Individual Configs: None +</source> + <translation>ŠŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½ŃŠµ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŠø: ŠŠµŃ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1148"/> + <source>Individual Config: MAC %ls +</source> + <translation>ŠŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½Š°Ń ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ: MAC %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1158"/> + <source>Individual Config: VM NIC: %ls slot %u, MAC %ls +</source> + <translation>ŠŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½Š°Ń ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ: ŠŠ NIC: %ls ŃŠ»Š¾Ń %u, MAC %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1161"/> + <source>Individual Config: VM NIC: %ls slot %u, MAC %Rhrc +</source> + <translation>ŠŠ½Š“ŠøŠ²ŠøŠ“ŃŠ°Š»ŃŠ½Š°Ń ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ: ŠŠ NIC: %ls ŃŠ»Š¾Ń %u, MAC %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1166"/> + <source> Fixed Address: %ls +</source> + <translation> Š¤ŠøŠŗŃŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ Š°Š“ŃŠµŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1168"/> + <source> Fixed Address: dynamic +</source> + <translation> Š¤ŠøŠŗŃŠøŃŠ¾Š²Š°Š½Š½ŃŠ¹ Š°Š“ŃŠµŃ: Š“ŠøŠ½Š°Š¼ŠøŃŠµŃŠŗŠøŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1194"/> + <source>Extension Packs: %u +</source> + <translation>ŠŠ°ŠŗŠµŃŃ ŃŠ°ŃŃŠøŃŠµŠ½ŠøŠ¹: %u +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1220"/> + <source>Pack no.%2zu: %ls +Version: %ls +Revision: %u +Edition: %ls +Description: %ls +VRDE Module: %ls +Usable: %RTbool +Why unusable: %ls +</source> + <translation>ŠŠ°ŠŗŠµŃ no.%2zu: %ls +ŠŠµŃŃŠøŃ: %ls +Š ŠµŠ²ŠøŠ·ŠøŃ: %u +Š ŠµŠ“Š°ŠŗŃŠøŃ: %ls +ŠŠæŠøŃŠ°Š½ŠøŠµ: %ls +VRDE Š¼Š¾Š“ŃŠ»Ń: %ls +ŠŠ¾Š“Š½ŃŠ¹: %RTbool +ŠŠ¾ŃŠµŠ¼Ń Š½Šµ Š³Š¾Š“ŠµŠ½: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1276"/> + <source>Video Input Devices: %u +</source> + <translation>Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š° Š²Š²Š¾Š“Š° Š²ŠøŠ“ŠµŠ¾: %u +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1305"/> + <source>Supported %d screen shot formats: +</source> + <translation> + <numerusform>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠ¹ %d ŃŠ¾ŃŠ¼Š°Ń ŃŠ½ŠøŠ¼ŠŗŠ° ŃŠŗŃŠ°Š½Š°: +</numerusform> + <numerusform>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠµ %d ŃŠ¾ŃŠ¼Š°ŃŠ° ŃŠ½ŠøŠ¼ŠŗŠ° ŃŠŗŃŠ°Š½Š°: +</numerusform> + <numerusform>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠµ %d ŃŠ¾ŃŠ¼Š°ŃŠ¾Š² ŃŠ½ŠøŠ¼ŠŗŠ° ŃŠŗŃŠ°Š½Š°: +</numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1334"/> + <source>Supported %d cloud providers: +</source> + <translation> + <numerusform>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠ¹ %d Š¾Š±Š»Š°ŃŠ½ŃŠ¹ ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃ: +</numerusform> + <numerusform>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠµ %d Š¾Š±Š»Š°ŃŠ½ŃŃ
ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃŠ°: +</numerusform> + <numerusform>ŠŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŠ¼ŃŠµ %d Š¾Š±Š»Š°ŃŠ½ŃŃ
ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃŠ¾Š²: +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1342"/> + <source>Short Name: %ls +</source> + <translation>ŠŃŠ°ŃŠŗŠ¾Šµ ŠøŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1378"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1381"/> + <source>Provider GUID: %ls +</source> + <translation>GUID ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1397"/> + <source>Property: </source> + <translation>Š”Š²Š¾Š¹ŃŃŠ²Š¾: </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1435"/> + <source>CPU Profile #%02zu: +</source> + <translation>ŠŃŠ¾ŃŠøŠ»Ń Š¦ŠŠ£ #%02zu: +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1436"/> + <source> Architecture: %s +</source> + <translation> ŠŃŃ
ŠøŃŠµŠŗŃŃŃŠ°: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1437"/> + <source> Name: %ls +</source> + <translation> ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1439"/> + <source> Full Name: %ls +</source> + <translation> ŠŠ¾Š»Š½Š¾Šµ ŠøŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1689"/> + <source>%sDrive: %ls +</source> + <translation>%sŠŠøŃŠŗ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1691"/> + <source>%sDrive: %Rhrc +</source> + <translation>%sŠŠøŃŠŗ: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1696"/> + <source>Model: %Rhrc +</source> + <translation>ŠŠ¾Š“ŠµŠ»Ń: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1698"/> + <source>Model: "%ls" +</source> + <translation>ŠŠ¾Š“ŠµŠ»Ń: "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1700"/> + <source>Model: unknown/inaccessible +</source> + <translation>ŠŠ¾Š“ŠµŠ»Ń: Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾/Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š¾ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1710"/> + <source>Further disk and partitioning information is not available for drive "%ls". (E_ACCESSDENIED) +</source> + <translation>ŠŠ°Š»ŃŠ½ŠµŠ¹ŃŠ°Ń ŠøŠ½ŃŠ¾ŃŠ¼Š°ŃŠøŃ Š¾ Š“ŠøŃŠŗŠµ Šø ŠµŠ³Š¾ ŃŠ°Š·Š“ŠµŠ»Š°Ń
Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š° Š“Š»Ń Š“ŠøŃŠŗŠ° "%ls". (E_ACCESSDENIED) +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1723"/> + <source>Size: %llu bytes (%Rhcb) +</source> + <translation> + <numerusform>Š Š°Š·Š¼ŠµŃ: %llu Š±Š°Š¹Ń (%Rhcb) +</numerusform> + <numerusform>Š Š°Š·Š¼ŠµŃ: %llu Š±Š°Š¹ŃŠ° (%Rhcb) +</numerusform> + <numerusform>Š Š°Š·Š¼ŠµŃ: %llu Š±Š°Š¹Ń (%Rhcb) +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1725"/> + <source>Size: %Rhcb +</source> + <translation>Š Š°Š·Š¼ŠµŃ: %Rhcb +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1728"/> + <source>Size: %Rhrc +</source> + <translation>Š Š°Š·Š¼ŠµŃ: %Rhrc +</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1735"/> + <source>Sector Size: %u bytes +</source> + <translation> + <numerusform>Š Š°Š·Š¼ŠµŃ ŃŠµŠŗŃŠ¾ŃŠ°: %u Š±Š°Š¹Ń +</numerusform> + <numerusform>Š Š°Š·Š¼ŠµŃ ŃŠµŠŗŃŠ¾ŃŠ°: %u Š±Š°Š¹ŃŠ° +</numerusform> + <numerusform>Š Š°Š·Š¼ŠµŃ ŃŠµŠŗŃŠ¾ŃŠ°: %u Š±Š°Š¹Ń +</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1738"/> + <source>Sector Size: %Rhrc +</source> + <translation>Š Š°Š·Š¼ŠµŃ ŃŠµŠŗŃŠ¾ŃŠ°: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1745"/> + <source>Scheme: %s +</source> + <translation>Š”Ń
ŠµŠ¼Š°: %s +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1748"/> + <source>Scheme: %Rhrc +</source> + <translation>Š”Ń
ŠµŠ¼Š°: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1756"/> + <source>Partitions: %Rhrc +</source> + <translation>Š Š°Š·Š“ŠµŠ»Ń: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1760"/> + <source>Partitions: None (or not able to grok them). +</source> + <translation>Š Š°Š·Š“ŠµŠ»Ń: ŠŠµŃ (ŠøŠ»Šø Š½ŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŃŠ°Š·Š¾Š±ŃŠ°ŃŃŃŃ Š² Š½ŠøŃ
). +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1764"/> + <source>Partitions: First Last +## Type Byte Size Byte Offset Cyl/Head/Sec Cyl/Head/Sec Active +</source> + <translation>Š Š°Š·Š“ŠµŠ»Ń: ŠŠµŃŠ²ŃŠ¹ ŠŠ¾ŃŠ»ŠµŠ“Š½ŠøŠ¹ +## Š¢ŠøŠæ Š Š°Š·Š¼ŠµŃ Š±Š°Š¹Ń Š”Š¼ŠµŃŠµŠ½ŠøŠµ Š±Š°Š¹Ń Š¦ŠøŠ»/ŠŠ¾Š»/Š”ŠµŠŗŃ Š¦ŠøŠ»/ŠŠ¾Š»/Š”ŠµŠŗŃ ŠŠŗŃŠøŠ²Š½ŃŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1767"/> + <source>Partitions: First Last +## Type Size Start Cyl/Head/Sec Cyl/Head/Sec Active +</source> + <translation>Š Š°Š·Š“ŠµŠ»Ń: ŠŠµŃŠ²ŃŠ¹ ŠŠ¾ŃŠ»ŠµŠ“Š½ŠøŠ¹ +## Š¢ŠøŠæ Š Š°Š·Š¼ŠµŃ Š”ŃŠ°ŃŃ Š¦ŠøŠ»/ŠŠ¾Š»/Š”ŠµŠŗŃ Š¦ŠøŠ»/ŠŠ¾Š»/Š”ŠµŠŗŃ ŠŠŗŃŠøŠ²Š½ŃŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1826"/> + <source>Partitions: +## %-*s Uuid Byte Size Byte Offset Active Name +</source> + <translation>Š Š°Š·Š“ŠµŠ»Ń: +## %-*s Uuid Š Š°Š·Š¼ŠµŃ Š±Š°Š¹Ń Š”Š¼ŠµŃŠµŠ½ŠøŠµ Š±Š°Š¹Ń ŠŠŗŃŠøŠ²ŠµŠ½ ŠŠ¼Ń +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1829"/> + <location filename="../VBoxManageList.cpp" line="1834"/> + <source>Type</source> + <translation>Š¢ŠøŠæ</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1831"/> + <source>Partitions: +## %-*s Uuid Size Start Active Name +</source> + <translation>Š Š°Š·Š“ŠµŠ»Ń: +## %-*s Uuid Š Š°Š·Š¼ŠµŃ Š”ŃŠ°ŃŃ ŠŠŗŃŠøŠ²ŠµŠ½ ŠŠ¼Ń +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2043"/> + <source>Description: %ls +</source> + <translation>ŠŠæŠøŃŠ°Š½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2046"/> + <source>Family ID: %ls +</source> + <translation>ID ŃŠµŠ¼ŠµŠ¹ŃŃŠ²Š°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2049"/> + <source>Family Desc: %ls +</source> + <translation>ŠŠæŠøŃŠ°Š½ŠøŠµ ŃŠµŠ¼ŠµŠ¹ŃŃŠ²Š°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2052"/> + <source>64 bit: %RTbool +</source> + <translation>64 Š±ŠøŃ: %RTbool +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2075"/> + <location filename="../VBoxManageList.cpp" line="2097"/> + <source>Name: %ls + +</source> + <translation>ŠŠ¼Ń: %ls + +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2134"/> + <source>Host CPUIDs: + +Leaf no. EAX EBX ECX EDX +</source> + <translation>CPUID Ń
Š¾ŃŃŠ°: + +ŠŠøŃŃ no. EAX EBX ECX EDX +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2166"/> + <source>base</source> + <translation>Š±Š°Š·Š¾Š²ŃŠ¹</translation> + </message> + <message> + <source>Network: %ls +</source> + <translation type="vanished">Š”ŠµŃŃ: %ls +</translation> + </message> + <message> + <source>IPv6 Enabled: %s +</source> + <translation type="vanished">IPv6 Š²ŠŗŠ»ŃŃŠµŠ½: %s +</translation> + </message> + <message> + <source>IPv6 Prefix: %ls +</source> + <translation type="vanished">IPv6 ŠæŃŠµŃŠøŠŗŃ: %ls +</translation> + </message> + <message> + <source>DHCP Enabled: %s +</source> + <translation type="vanished">DHCP Š²ŠŗŠ»ŃŃŠµŠ½: %s +</translation> + </message> + <message> + <source>Port-forwarding (ipv4) +</source> + <translation type="vanished">ŠŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŠµ ŠæŠ¾ŃŃŠ¾Š² (ipv4) +</translation> + </message> + <message> + <source>Port-forwarding (ipv6) +</source> + <translation type="vanished">ŠŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŠµ ŠæŠ¾ŃŃŠ¾Š² (ipv6) +</translation> + </message> + <message> + <source>loopback mappings (ipv4) +</source> + <translation type="vanished">Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŠµ Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š¹ ŠæŠµŃŠ»Šø (ipv4) +</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2388"/> + <source>Unknown subcommand "%s".</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š° "%s".</translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2399"/> + <source>Missing subcommand for "list" command. +</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š° Š“Š»Ń ŠŗŠ¾Š¼Š°Š½Š“Ń "list". +</translation> + </message> +</context> +<context> + <name>Metrics</name> + <message> + <location filename="../VBoxManageMetrics.cpp" line="90"/> + <source>Invalid machine name: '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń Š¼Š°ŃŠøŠ½Ń: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="128"/> + <source>host</source> + <translation>Ń
Š¾ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="138"/> + <source>unknown</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="149"/> + <source>The following metrics were modified: + +Object Metric +---------- -------------------- +</source> + <translation>Š”Š»ŠµŠ“ŃŃŃŠøŠµ Š¼ŠµŃŃŠøŠŗŠø ŠøŠ·Š¼ŠµŠ½ŠµŠ½Ń: + +ŠŠ±ŃŠµŠŗŃ ŠŠµŃŃŠøŠŗŠ° +---------- -------------------- +</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="163"/> + <source>No metrics match the specified filter!</source> + <translation>ŠŠµ Š½Š°Š¹Š“ŠµŠ½Š¾ Š¼ŠµŃŃŠøŠŗ, ŠæŠ¾Š“Ń
Š¾Š“ŃŃŠøŃ
ŠæŠ¾Š“ ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ ŃŠøŠ»ŃŃŃ!</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="197"/> + <source>Object Metric Unit Minimum Maximum Period Count Description +--------------- ---------------------------------------- ---- ---------- ---------- ---------- ---------- ----------- +</source> + <translation>ŠŠ±ŃŠµŠŗŃ ŠŠµŃŃŠøŠŗŠ° ŠŠ“. ŠŠøŠ½ ŠŠ°ŠŗŃ ŠŠµŃŠøŠ¾Š“ ŠŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ ŠŠæŠøŃŠ°Š½ŠøŠµ +--------------- ---------------------------------------- ---- ---------- ---------- ---------- ---------- ----------- +</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="240"/> + <location filename="../VBoxManageMetrics.cpp" line="249"/> + <location filename="../VBoxManageMetrics.cpp" line="412"/> + <location filename="../VBoxManageMetrics.cpp" line="421"/> + <source>Missing argument to '%s'</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="243"/> + <location filename="../VBoxManageMetrics.cpp" line="415"/> + <source>Invalid value for 'period' parameter: '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ Š“Š»Ń ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ° 'period': '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="252"/> + <location filename="../VBoxManageMetrics.cpp" line="424"/> + <source>Invalid value for 'samples' parameter: '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š·Š½Š°ŃŠµŠ½ŠøŠµ Š“Š»Ń ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ° 'samples': '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="319"/> + <source>Object Metric Values +--------------- ---------------------------------------- -------------------------------------------- +</source> + <translation>ŠŠ±ŃŠµŠŗŃ ŠŠµŃŃŠøŠŗŠ° ŠŠ½Š°ŃŠµŠ½ŠøŃ +--------------- ---------------------------------------- -------------------------------------------- +</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="483"/> + <source>The background process holding collected metrics will shutdown +in few seconds, discarding all collected data and parameters.</source> + <translation>Š¤Š¾Š½Š¾Š²ŃŠ¹ ŠæŃŠ¾ŃŠµŃŃ, ŃŠ“ŠµŃŠ¶ŠøŠ²Š°ŃŃŠøŠ¹ ŃŠ¾Š±ŃŠ°Š½Š½ŃŠµ Š¼ŠµŃŃŠøŠŗŠø Š·Š°Š²ŠµŃŃŠøŃŃŃ Š² +ŃŠµŃŠµŠ½ŠøŠµ Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠøŃ
ŃŠµŠŗŃŠ½Š“, ŃŠµŃŃŃ Š²ŃŠµ ŃŠ¾Š±ŃŠ°Š½Š½ŃŠµ Š“Š°Š½Š½ŃŠµ Šø +ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ.</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="492"/> + <source>Time stamp Object Metric Value +</source> + <translation>ŠŃŠµŠ¼Ń ŠŠ±ŃŠµŠŗŃ ŠŠµŃŃŠøŠŗŠ° ŠŠ½Š°ŃŠµŠ½ŠøŠµ +</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="639"/> + <source>Subcommand missing</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="658"/> + <source>Invalid subcommand '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠæŠ¾Š“ŠŗŠ¾Š¼Š°Š½Š“Š° '%s'</translation> + </message> +</context> +<context> + <name>Misc</name> + <message> + <location filename="../VBoxManageMisc.cpp" line="66"/> + <location filename="../VBoxManageMisc.cpp" line="760"/> + <location filename="../VBoxManageMisc.cpp" line="789"/> + <location filename="../VBoxManageMisc.cpp" line="824"/> + <location filename="../VBoxManageMisc.cpp" line="950"/> + <source>Incorrect number of parameters</source> + <translation>ŠŠµŠŗŠ¾ŃŃŠµŠŗŃŠ½Š¾Šµ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="79"/> + <location filename="../VBoxManageMisc.cpp" line="799"/> + <source>Cannot convert filename "%s" to absolute path: %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ ŠøŠ¼Ń ŃŠ°Š¹Š»Š° "%s" Š² Š°Š±ŃŠ¾Š»ŃŃŠ½ŃŠ¹ ŠæŃŃŃ: %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="125"/> + <location filename="../VBoxManageMisc.cpp" line="354"/> + <location filename="../VBoxManageMisc.cpp" line="530"/> + <location filename="../VBoxManageMisc.cpp" line="1075"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="132"/> + <location filename="../VBoxManageMisc.cpp" line="683"/> + <source>Invalid option -%c</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń Š¾ŠæŃŠøŃ -%c</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="133"/> + <location filename="../VBoxManageMisc.cpp" line="685"/> + <source>Invalid option case %i</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š²Š°ŃŠøŠ°Š½Ń Š¾ŠæŃŠøŠø %i</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="136"/> + <location filename="../VBoxManageMisc.cpp" line="688"/> + <source>unknown option: %s +</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="139"/> + <location filename="../VBoxManageMisc.cpp" line="692"/> + <source>error: %Rrs</source> + <translation>Š¾ŃŠøŠ±ŠŗŠ°: %Rrs</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="145"/> + <location filename="../VBoxManageMisc.cpp" line="370"/> + <location filename="../VBoxManageMisc.cpp" line="540"/> + <source>VM name required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠøŠ¼Ń ŠŠ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="162"/> + <source>Machine delete failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ Š¼Š°ŃŠøŠ½Ń</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="256"/> + <source>Parameter --name is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --name</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="298"/> + <source>Virtual machine '%ls' is created%s. +UUID: %s +Settings file: '%ls' +</source> + <translation>ŠŠøŃŃŃŠ°Š»ŃŠ½Š°Ń Š¼Š°ŃŠøŠ½Š° '%ls' ŃŠ¾Š·Š“Š°Š½Š°%s. +UUID: %s +Š¤Š°Š¹Š» Š½Š°ŃŃŃŠ¾ŠµŠŗ: '%ls' +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="301"/> + <source> and registered</source> + <translation> Šø Š·Š°ŃŠµŠ³ŠøŃŃŃŠøŃŠ¾Š²Š°Š½Š°</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="343"/> + <location filename="../VBoxManageMisc.cpp" line="1388"/> + <source>RTPathAbs(%s,,) failed with rc=%Rrc</source> + <translation>RTPathAbs(%s,,) Š·Š°Š²ŠµŃŃŠµŠ½ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ rc=%Rrc</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="394"/> + <source>Move VM failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠµŃŠµŠ¼ŠµŃŃŠøŃŃ ŠŠ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="399"/> + <source>Machine has been successfully moved into %s +</source> + <translation>ŠŠ°ŃŠøŠ½Š° ŃŃŠæŠµŃŠ½Š¾ ŠæŠµŃŠµŠ¼ŠµŃŠµŠ½Š° Š² %s +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="400"/> + <source>the same location</source> + <translation>ŃŠ¾ Š¶Šµ Š¼ŠµŃŃŠ¾</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="510"/> + <source>Invalid clone mode '%s' +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠµŠ¶ŠøŠ¼ ŠŗŠ»Š¾Š½ŠøŃŠ¾Š²Š°Š½ŠøŃ '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="515"/> + <source>Invalid clone options '%s' +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ Š¾ŠæŃŠøŠø ŠŗŠ»Š¾Š½ŠøŃŠ¾Š²Š°Š½ŠøŃ '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="562"/> + <source>%s Clone</source> + <translation>ŠŠ»Š¾Š½ %s</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="596"/> + <source>Clone VM failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠŗŠ»Š¾Š½ŠøŃŠ¾Š²Š°ŃŃ ŠŠ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="603"/> + <source>Machine has been successfully cloned as "%ls" +</source> + <translation>ŠŠ°ŃŠøŠ½Š° ŃŃŠæŠµŃŠ½Š¾ ŠŗŠ»Š¾Š½ŠøŃŠ¾Š²Š°Š½Š° ŠŗŠ°Šŗ "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="672"/> + <source>Parameter to option --putenv must not contain any newline character</source> + <translation>ŠŠ°ŃŠ°Š¼ŠµŃŃ Šŗ Š¾ŠæŃŠøŠø --putenv Š½Šµ Š“Š¾Š»Š¶ŠµŠ½ ŃŠ¾Š“ŠµŃŠ¶Š°ŃŃ ŠæŠµŃŠµŠ²Š¾Š“Š¾Š² ŃŃŃŠ¾ŠŗŠø</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="698"/> + <source>at least one VM name or uuid required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ Ń
Š¾ŃŃ Š±Ń Š¾Š“Š½Š¾ ŠøŠ¼Ń ŠŠ ŠøŠ»Šø uuid</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="716"/> + <source>Waiting for VM "%s" to power on... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ Š·Š°ŠæŃŃŠŗŠ° ŠŠ "%s"... +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="731"/> + <source>VM "%s" has been successfully started. +</source> + <translation>ŠŠ "%s" ŃŃŠæŠµŃŠ½Š¾ Š·Š°ŠæŃŃŠµŠ½Š°. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="844"/> + <location filename="../VBoxManageMisc.cpp" line="880"/> + <source>Key: %ls, Value: %ls +</source> + <translation>ŠŠ»ŃŃ: %ls, ŠŠ½Š°ŃŠµŠ½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="853"/> + <location filename="../VBoxManageMisc.cpp" line="889"/> + <source>Value: %ls +</source> + <translation>ŠŠ½Š°ŃŠµŠ½ŠøŠµ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="855"/> + <location filename="../VBoxManageMisc.cpp" line="891"/> + <source>No value set! +</source> + <translation>ŠŠµ Š·Š°Š“Š°Š½Š¾ ŠŗŠ°ŠŗŠ¾Šµ-Š»ŠøŠ±Š¾ Š·Š½Š°ŃŠµŠ½ŠøŠµ! +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="903"/> + <location filename="../VBoxManageMisc.cpp" line="1315"/> + <source>Not enough parameters</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="916"/> + <location filename="../VBoxManageMisc.cpp" line="938"/> + <source>Too many parameters</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="972"/> + <source>Invalid hwvirtexclusive argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ hwvirtexclusive '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="979"/> + <source>Warning: 'vrdpauthlibrary' is deprecated. Use 'vrdeauthlibrary'. +</source> + <translation>ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: 'vrdpauthlibrary' ŃŃŃŠ°ŃŠµŠ». ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ 'vrdeauthlibrary'. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1009"/> + <source>Error parsing Log history count '%s'</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ ŃŠ°Š·Š¼ŠµŃŠ° ŠøŃŃŠ¾ŃŠøŠø Š¶ŃŃŠ½Š°Š»Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1044"/> + <source>Unknown proxy mode: '%s'</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½ŃŠ¹ ŃŠµŠ¶ŠøŠ¼ ŠæŃŠ¾ŠŗŃŠø: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1138"/> + <location filename="../VBoxManageMisc.cpp" line="1250"/> + <source>Machine name is given more than once: first '%s', then '%s'</source> + <translation>ŠŠ¼Ń Š¼Š°ŃŠøŠ½Ń Š“Š°Š½Š¾ Š±Š¾Š»ŠµŠµ Š¾Š“Š½Š¾Š³Š¾ ŃŠ°Š·Š°: ŃŠ½Š°ŃŠ°Š»Š° '%s', Š·Š°ŃŠµŠ¼ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1148"/> + <location filename="../VBoxManageMisc.cpp" line="1260"/> + <source>No machine was specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š° Š¼Š°ŃŠøŠ½Š°</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1151"/> + <location filename="../VBoxManageMisc.cpp" line="1262"/> + <source>No shared folder name (--name) was given</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń Š¾Š±ŃŠµŠ¹ ŠæŠ°ŠæŠŗŠø (--name)</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1153"/> + <source>Invalid shared folder name '%s': contains space</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń Š¾Š±ŃŠµŠ¹ ŠæŠ°ŠæŠŗŠø '%s': ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŠæŃŠ¾Š±ŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1155"/> + <source>Invalid shared folder name '%s': contains tabs</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń Š¾Š±ŃŠµŠ¹ ŠæŠ°ŠæŠŗŠø '%s': ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŃŠ°Š±ŃŠ»ŃŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1157"/> + <source>Invalid shared folder name '%s': contains newline</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń Š¾Š±ŃŠµŠ¹ ŠæŠ°ŠæŠŗŠø '%s': ŃŠ¾Š“ŠµŃŠ¶ŠøŃ ŠæŠµŃŠµŠ²Š¾Š“Ń ŃŃŃŠ¾Šŗ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1160"/> + <source>No host path (--hostpath) was given</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŠæŃŃŃ Ń
Š¾ŃŃŠ° (--hostpath)</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1164"/> + <source>RTAbsPath failed on '%s': %Rrc</source> + <translation>RTAbsPath Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1187"/> + <source>Machine '%s' is not currently running.</source> + <translation>ŠŠ°ŃŠøŠ½Š° '%s' ŃŠµŠ¹ŃŠ°Ń Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š°.</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1283"/> + <source>Machine '%s' is not currently running. +</source> + <translation>ŠŠ°ŃŠøŠ½Š° '%s' ŃŠµŠ¹ŃŠ°Ń Š½Šµ Š·Š°ŠæŃŃŠµŠ½Š°. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1374"/> + <location filename="../VBoxManageMisc.cpp" line="1459"/> + <source>Too many extension pack names given to "extpack uninstall"</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ ŠøŠ¼ŠµŠ½ ŠæŠ°ŠŗŠµŃŠ¾Š² ŃŠ°ŃŃŠøŃŠµŠ½ŠøŠ¹ ŃŠŗŠ°Š·Š°Š½Š¾ Š“Š»Ń "extpack uninstall"</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1383"/> + <source>No extension pack name was given to "extpack install"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠæŠ°ŠŗŠµŃŠ° ŃŠ°ŃŃŠøŃŠµŠ½ŠøŃ Š“Š»Ń "extpack install"</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1412"/> + <source>License accepted. +</source> + <translation>ŠŠøŃŠµŠ½Š·ŠøŃ ŠæŃŠøŠ½ŃŃŠ°. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1416"/> + <source>Do you agree to these license terms and conditions (y/n)? </source> + <translation>ŠŃ ŃŠ¾Š³Š»Š°ŃŠ½Ń Ń ŃŃŠøŠ¼Šø Š¾ŠæŃŠµŠ“ŠµŠ»ŠµŠ½ŠøŃŠ¼Šø Šø ŃŃŠ»Š¾Š²ŠøŃŠ¼Šø Š»ŠøŃŠµŠ½Š·ŠøŠø (y/n)? </translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1421"/> + <source>Installation of "%ls" aborted. +</source> + <translation>Š£ŃŃŠ°Š½Š¾Š²ŠŗŠ° "%ls" ŠæŃŠµŃŠ²Š°Š½Š°. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1425"/> + <source>License accepted. For batch installation add +--accept-license=%s +to the VBoxManage command line. + +</source> + <translation>ŠŠøŃŠµŠ½Š·ŠøŃ ŠæŃŠøŠ½ŃŃŠ°. ŠŠ»Ń ŠæŠ°ŠŗŠµŃŠ½Š¾Š¹ ŃŃŃŠ°Š½Š¾Š²ŠŗŠø Š“Š¾Š±Š°Š²ŃŃŠµ +--accept-license=%s +Š² ŠŗŠ¾Š¼Š°Š½Š“Š½ŃŃ ŃŃŃŠ¾ŠŗŃ VBoxManage. + +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1433"/> + <source>Failed to install "%s"</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŃŃŠ°Š½Š¾Š²ŠøŃŃ "%s"</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1435"/> + <source>Successfully installed "%ls". +</source> + <translation>Š£ŃŠæŠµŃŠ½Š¾ ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½Š¾ "%ls". +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1468"/> + <source>No extension pack name was given to "extpack uninstall"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠæŠ°ŠŗŠµŃŠ° ŃŠ°ŃŃŠøŃŠµŠ½ŠøŃ Š“Š»Ń "extpack uninstall"</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1474"/> + <source>Failed to uninstall "%s"</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ "%s"</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1476"/> + <source>Successfully uninstalled "%s". +</source> + <translation>Š£ŃŠæŠµŃŠ½Š¾ ŃŠ“Š°Š»ŠµŠ½Š¾ "%s". +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1484"/> + <source>Successfully performed extension pack cleanup +</source> + <translation>Š£ŃŠæŠµŃŠ½Š¾ ŠæŃŠ¾ŠøŠ·Š²ŠµŠ“ŠµŠ½Š° Š¾ŃŠøŃŃŠŗŠ° ŠæŠ°ŠŗŠµŃŠ° ŃŠ°ŃŃŠøŃŠµŠ½ŠøŃ +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1526"/> + <location filename="../VBoxManageMisc.cpp" line="1679"/> + <location filename="../VBoxManageMisc.cpp" line="1718"/> + <location filename="../VBoxManageMisc.cpp" line="1731"/> + <location filename="../VBoxManageMisc.cpp" line="1766"/> + <location filename="../VBoxManageMisc.cpp" line="1777"/> + <location filename="../VBoxManageMisc.cpp" line="1784"/> + <source>RTPathAbs failed on '%s': %Rrc</source> + <translation>RTPathAbs Š·Š°Š²ŠµŃŃŠøŠ»ŃŃ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹ Š½Š° '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1542"/> + <source>No ISO specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ISO</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1587"/> + <source>Detected '%s' to be: +</source> + <translation>ŠŠ±Š½Š°ŃŃŠ¶ŠµŠ½Š½ŃŠ¹ '%s': +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1588"/> + <source> OS TypeId = %ls + OS Version = %ls + OS Flavor = %ls + OS Languages = %ls + OS Hints = %ls +</source> + <translation> ID ŃŠøŠæŠ° ŠŠ” = %ls + ŠŠµŃŃŠøŃ ŠŠ” = %ls + ŠŃŠ¾Š±ŠµŠ½Š½Š¾ŃŃŃ ŠŠ” = %ls + ŠÆŠ·ŃŠŗŠø ŠŠ” = %ls + ŠŠ¾Š“ŃŠŗŠ°Š·ŠŗŠø ŠŠ” = %ls +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1671"/> + <source>VM name/UUID given more than once!</source> + <translation>ŠŠ¼Ń ŠŠ/UUID ŃŠŗŠ°Š·Š°Š½Ń Š½ŠµŃŠŗŠ¾Š»ŃŠŗŠ¾ ŃŠ°Š·!</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1813"/> + <source>Missing VM name/UUID</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ¼Ń ŠŠ/UUID</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1865"/> + <source>Machine '%ls' is currently running</source> + <translation>ŠŠ°ŃŠøŠ½Š° '%ls' ŃŠµŠ¹ŃŠ°Ń ŃŠ°Š±Š¾ŃŠ°ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1871"/> + <source>%s unattended installation of %s in machine '%ls' (%ls). +</source> + <translation>%s unattended ŃŃŃŠ°Š½Š¾Š²ŠŗŠ° %s Š² Š¼Š°ŃŠøŠ½Ń '%ls' (%ls). +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1872"/> + <source>Preparing</source> + <translation>ŠŠ¾Š“Š³Š¾ŃŠ¾Š²ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1872"/> + <source>Starting</source> + <translation>ŠŠ°ŠæŃŃŠŗ</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1885"/> + <source>Using values: +</source> + <translation>ŠŃŠæŠ¾Š»ŃŠ·ŃŠµŠ¼ŃŠµ Š·Š½Š°ŃŠµŠ½ŠøŃ: +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1892"/> + <location filename="../VBoxManageMisc.cpp" line="1900"/> + <location filename="../VBoxManageMisc.cpp" line="1952"/> + <source> %32s = failed: %Rhrc +</source> + <translation> %32s = Š·Š°Š²ŠµŃŃŠµŠ½Š¾ Ń Š¾ŃŠøŠ±ŠŗŠ¾Š¹: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1955"/> + <source> %32 = failed: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1971"/> + <source>VM '%ls' (%ls) is ready to be started (e.g. VBoxManage startvm). +</source> + <translation>ŠŠ '%ls' (%ls) Š³Š¾ŃŠ¾Š²Š° Šŗ Š·Š°ŠæŃŃŠŗŃ (Š½Š°ŠæŃŠøŠ¼ŠµŃ, VBoxManage startvm). +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1990"/> + <source>Waiting for VM '%ls' to power on... +</source> + <translation>ŠŠ¶ŠøŠ“Š°Š½ŠøŠµ Š·Š°ŠæŃŃŠŗŠ° ŠŠ '%ls'... +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2005"/> + <source>VM '%ls' (%ls) has been successfully started. +</source> + <translation>ŠŠ '%ls' (%ls) ŃŃŠæŠµŃŠ½Š¾ Š·Š°ŠæŃŃŠµŠ½Š°. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2137"/> + <location filename="../VBoxManageMisc.cpp" line="2187"/> + <location filename="../VBoxManageMisc.cpp" line="2247"/> + <location filename="../VBoxManageMisc.cpp" line="2345"/> + <source>Parameter --provider is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --provider</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2139"/> + <location filename="../VBoxManageMisc.cpp" line="2189"/> + <location filename="../VBoxManageMisc.cpp" line="2249"/> + <location filename="../VBoxManageMisc.cpp" line="2347"/> + <source>Parameter --profile is required</source> + <translation>Š¢ŃŠµŠ±ŃŠµŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃ --profile</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2168"/> + <source>Provider %ls: profile '%ls' was updated. +</source> + <translation>ŠŃŠ¾Š²Š°Š¹Š“ŠµŃ %ls: ŠæŃŠ¾ŃŠøŠ»Ń '%ls' Š¾Š±Š½Š¾Š²Š»ŠµŠ½. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2210"/> + <source>Provider GUID: %ls +</source> + <translation>GUID ŠæŃŠ¾Š²Š°Š¹Š“ŠµŃŠ°: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2226"/> + <source>Property: </source> + <translation>Š”Š²Š¾Š¹ŃŃŠ²Š¾: </translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2331"/> + <source>Provider %ls: profile '%ls' was added. +</source> + <translation>ŠŃŠ¾Š²Š°Š¹Š“ŠµŃ %ls: ŠæŃŠ¾ŃŠøŠ»Ń '%ls' Š“Š¾Š±Š°Š²Š»ŠµŠ½. +</translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2374"/> + <source>Provider %ls: profile '%ls' was deleted. +</source> + <translation>ŠŃŠ¾Š²Š°Š¹Š“ŠµŃ %ls: ŠæŃŠ¾ŃŠøŠ»Ń '%ls' ŃŠ“Š°Š»ŠµŠ½. +</translation> + </message> +</context> +<context> + <name>ModifyVM</name> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="467"/> + <source>Warning: '--vrdp%s' is deprecated. Use '--vrde%s'. +</source> + <translation>ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: '--vrdp%s' ŃŃŃŠ°ŃŠµŠ». ŠŃŠæŠ¾Š»ŃŠ·ŃŠ¹ŃŠµ '--vrde%s'. +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="578"/> + <source>Invalid %s number %u</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š½Š¾Š¼ŠµŃ %s %u</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="607"/> + <location filename="../VBoxManageModifyVM.cpp" line="2089"/> + <source>Not enough parameters</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="670"/> + <source>Cannot open file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ ŃŠ°Š¹Š» "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="678"/> + <source>Cannot get size of file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ ŃŠ°Š¹Š»Š° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="684"/> + <source>File "%s" is bigger than 256KByte</source> + <translation>Š¤Š°Š¹Š» "%s" Š±Š¾Š»ŃŃŠµ 256 ŠŠŠ°Š¹Ń</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="692"/> + <source>Cannot read contents of file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŃŠµŃŃŃ ŃŠ¾Š“ŠµŃŠ¶ŠøŠ¼Š¾Šµ ŃŠ°Š¹Š»Š° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="743"/> + <source>Invalid --firmware argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --firmware '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="814"/> + <source>Invalid --paravirtprovider argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --paravirtprovider '%s'</translation> + </message> + <message> + <source>Missing or Invalid argument to '%s'</source> + <translation type="vanished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ»Šø Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="841"/> + <location filename="../VBoxManageModifyVM.cpp" line="1989"/> + <location filename="../VBoxManageModifyVM.cpp" line="2381"/> + <location filename="../VBoxManageModifyVM.cpp" line="2460"/> + <location filename="../VBoxManageModifyVM.cpp" line="2503"/> + <location filename="../VBoxManageModifyVM.cpp" line="2939"/> + <source>Missing or invalid argument to '%s'</source> + <translation type="unfinished">ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ»Šø Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="985"/> + <source>Invalid --graphicscontroller argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --graphicscontroller '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1051"/> + <source>Invalid --biosbootmenu argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --biosbootmenu '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1075"/> + <source>Invalid --biosapic argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --biosapic '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1122"/> + <source>Invalid boot device '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š·Š°Š³ŃŃŠ·Š¾ŃŠ½Š¾Šµ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1202"/> + <source>Invalid --idecontroller argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --idecontroller '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1232"/> + <source>Invalid --usb argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --usb '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1307"/> + <source>Invalid --scsitype argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --scsitype '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1362"/> + <location filename="../VBoxManageModifyVM.cpp" line="1370"/> + <source>Invalid host DVD drive name "%s"</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń DVD Š“ŠøŃŠŗŠ¾Š²Š¾Š“Š° Ń
Š¾ŃŃŠ° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1436"/> + <source>Invalid host floppy drive name "%s"</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń ŃŠ»Š¾ŠæŠæŠø Š“ŠøŃŠŗŠ¾Š²Š¾Š“Š° Ń
Š¾ŃŃŠ° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1516"/> + <source>Invalid --nicproperty%d argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --nicproperty%d '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1523"/> + <source>Error: Failed to allocate memory for --nicproperty%d '%s' +</source> + <translation>ŠŃŠøŠ±ŠŗŠ°: ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠ“ŠµŠ»ŠøŃŃ ŠæŠ°Š¼ŃŃŃ Š“Š»Ń --nicproperty%d '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1597"/> + <source>Invalid NIC type '%s' specified for NIC %u</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ NIC '%s', ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ Š“Š»Ń NIC %u</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1632"/> + <source>Invalid boot priority '%u' specfied for NIC %u</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Ń ŠæŃŠøŠ¾ŃŠøŃŠµŃ Š·Š°Š³ŃŃŠ·ŠŗŠø '%u' ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ Š“Š»Ń NIC %u</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1654"/> + <source>Unknown promiscuous mode policy '%s'</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŠæŠ¾Š»ŠøŃŠøŠŗŠ° Š½ŠµŃŠ°Š·Š±Š¾ŃŃŠøŠ²Š¾Š³Š¾ ŃŠµŠ¶ŠøŠ¼Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1789"/> + <source>Invalid type '%s' specfied for NIC %u</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ '%s', ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ Š“Š»Ń NIC %u</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2073"/> + <source>Invalid proto '%s' specfied for NIC %u</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŃŠ¾ŃŠ¾ŠŗŠ¾Š» '%s', ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ Š“Š»Ń NIC %u</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2291"/> + <source>Invalid type '%s' specfied for pointing device</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ '%s', ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ Š“Š»Ń ŃŠŗŠ°Š·Š°ŃŠµŠ»ŃŠ½Š¾Š³Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š°</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2336"/> + <source>Invalid type '%s' specfied for keyboard</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ '%s', ŃŠŗŠ°Š·Š°Š½Š½ŃŠ¹ Š“Š»Ń ŠŗŠ»Š°Š²ŠøŠ°ŃŃŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2439"/> + <source>Invalid argument to '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2467"/> + <source>Error parsing UART I/O base '%s'</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š±Š°Š·Š¾Š²Š¾Š³Š¾ Š°Š“ŃŠµŃŠ° I/O UART '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2510"/> + <source>Error parsing LPT I/O base '%s'</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŠ°Š·Š±Š¾ŃŠµ Š±Š°Š·Š¾Š²Š¾Š³Š¾ Š°Š“ŃŠµŃŠ° I/O LPT '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2539"/> + <source>Invalid --audiocontroller argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --audiocontroller '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2561"/> + <source>Invalid --audiocodec argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --audiocodec '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2633"/> + <source>Invalid --audio argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --audio '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2673"/> + <source>Invalid --clipboard-mode argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --clipboard-mode '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2693"/> + <source>Invalid --clipboard-file-transfers argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --clipboard-file-transfers '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2718"/> + <source>Invalid --draganddrop argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --draganddrop '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2772"/> + <source>Invalid --vrdeproperty argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --vrdeproperty '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2780"/> + <source>Error: Failed to allocate memory for VRDE property '%s' +</source> + <translation>ŠŃŠøŠ±ŠŗŠ°: ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š²ŃŠ“ŠµŠ»ŠøŃŃ ŠæŠ°Š¼ŃŃŃ ŠæŠ¾Š“ ŃŠ²Š¾Š¹ŃŃŠ²Š¾ VRDE '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2842"/> + <source>Invalid --vrdeauthtype argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --vrdeauthtype '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2960"/> + <source>Invalid --usbrename parameters, nothing renamed</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ Šŗ --usbrename, Š½ŠøŃŠµŠ³Š¾ Š½Šµ ŠæŠµŃŠµŠøŠ¼ŠµŠ½Š¾Š²Š°Š½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3164"/> + <source>*** I/O APIC must be enabled for ICH9, enabling. *** +</source> + <translation>*** I/O APIC Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ Š²ŠŗŠ»ŃŃŠµŠ½ Š“Š»Ń ICH9, Š²ŠŗŠ»ŃŃŠµŠ½ŠøŠµ. *** +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3170"/> + <source>Invalid --chipset argument '%s' (valid: piix3,ich9)</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --chipset '%s' (Š“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ: piix3,ich9)</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3188"/> + <source>Invalid --iommu argument '%s' (valid: none,amd,automatic)</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --iommu '%s' (Š“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ: none,amd,automatic)</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3197"/> + <source>Warning: On Intel hosts, 'automatic' will not enable an IOMMU since the Intel IOMMU device is not supported yet. +</source> + <translation>ŠŃŠµŠ“ŃŠæŃŠµŠ¶Š“ŠµŠ½ŠøŠµ: ŠŠ° Ń
Š¾ŃŃŠ°Ń
Intel, 'automatic' Š½Šµ Š²ŠŗŠ»ŃŃŠ°ŠµŃ IOMMU, ŃŠ°Šŗ ŠŗŠ°Šŗ Intel IOMMU ŃŃŃŃŠ¾Š¹ŃŃŠ²Š° ŠµŃŠµ Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŃŃŃŃ. +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3202"/> + <source>Invalid --iommu argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --iommu '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3227"/> + <source>Invalid --tpm-type argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --tpm-type '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3284"/> + <source>Invalid list of screens specified +</source> + <translation>Š£ŠŗŠ°Š·Š°Š½ Š½ŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠæŠøŃŠ¾Šŗ ŃŠŗŃŠ°Š½Š¾Š² +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3306"/> + <source>Cannot convert filename "%s" to absolute path +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ ŠøŠ¼Ń ŃŠ°Š¹Š»Š° "%s" Š² Š°Š±ŃŠ¾Š»ŃŃŠ½ŃŠ¹ ŠæŃŃŃ +</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3336"/> + <location filename="../VBoxManageModifyVM.cpp" line="3345"/> + <source>Error parsing video resolution '%s' (expected <width>x<height>)</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŃŠ°Š·Š±Š¾ŃŠ° Š²ŠøŠ“ŠµŠ¾ ŃŠ°Š·ŃŠµŃŠµŠ½ŠøŃ '%s' (Š¾Š¶ŠøŠ“Š°ŠµŃŃŃ <ŃŠøŃŠøŠ½Š°>x<Š²ŃŃŠ¾ŃŠ°>)</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3420"/> + <source>Invalid --autostop-type argument '%s' (valid: disabled, savestate, poweroff, acpishutdown)</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --autostop-type '%s' (Š“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ: disabled, savestate, poweroff, acpishutdown)</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3440"/> + <source>Invalid --pciattach argument '%s' (valid: 'HB:HD.HF@GB:GD.GF' or just 'HB:HD.HF')</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --pciattach '%s' (Š“Š¾ŠæŃŃŃŠøŠ¼ŃŠµ: 'HB:HD.HF@GB:GD.GF' ŠøŠ»Šø ŠæŃŠ¾ŃŃŠ¾ 'HB:HD.HF')</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3458"/> + <source>Invalid --pcidetach argument '%s' (valid: 'HB:HD.HF')</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --pcidetach '%s' (Š“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹: 'HB:HD.HF')</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3492"/> + <source>Invalid --vm-process-priority '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ --vm-process-priority '%s'</translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3521"/> + <source>--testing-cfg-dword index %u is out of range: 0 thru 9</source> + <translation>ŠŠ½Š“ŠµŠŗŃ --testing-cfg-dword %u Š²Š½Šµ Š³ŃŠ°Š½ŠøŃ Š“ŠøŠ°ŠæŠ°Š·Š¾Š½Š°: 0 - 9</translation> + </message> +</context> +<context> + <name>Nat</name> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="96"/> + <source>Name: %ls +</source> + <translation>ŠŠ¼Ń: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="110"/> + <source>Network: %ls +</source> + <translation>Š”ŠµŃŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="113"/> + <source>Gateway: %ls +</source> + <translation>ŠØŠ»ŃŠ·: %ls +</translation> + </message> + <message> + <source>DHCP Sever: %s +</source> + <translation type="vanished">DHCP ŃŠµŃŠ²ŠµŃ: %s +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="106"/> + <location filename="../VBoxManageNATNetwork.cpp" line="116"/> + <location filename="../VBoxManageNATNetwork.cpp" line="119"/> + <location filename="../VBoxManageNATNetwork.cpp" line="125"/> + <source>Yes</source> + <translation>ŠŠ°</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="106"/> + <location filename="../VBoxManageNATNetwork.cpp" line="116"/> + <location filename="../VBoxManageNATNetwork.cpp" line="119"/> + <location filename="../VBoxManageNATNetwork.cpp" line="125"/> + <source>No</source> + <translation>ŠŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="122"/> + <source>IPv6 Prefix: %ls +</source> + <translation>IPv6 ŠæŃŠµŃŠøŠŗŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="125"/> + <source>IPv6 Default: %s +</source> + <translation>IPv6 ŠæŠ¾ ŃŠ¼Š¾Š»ŃŠ°Š½ŠøŃ: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="106"/> + <source>Enabled: %s +</source> + <translation>ŠŠŗŠ»ŃŃŠµŠ½Š¾: %s +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="116"/> + <source>DHCP Server: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="142"/> + <source>Port-forwarding (ipv4) +</source> + <translation type="unfinished">ŠŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŠµ ŠæŠ¾ŃŃŠ¾Š² (ipv4) +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="146"/> + <source>Port-forwarding (ipv6) +</source> + <translation type="unfinished">ŠŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŠµ ŠæŠ¾ŃŃŠ¾Š² (ipv6) +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="150"/> + <source>loopback mappings (ipv4) +</source> + <translation type="unfinished">Š¾ŃŠ¾Š±ŃŠ°Š¶ŠµŠ½ŠøŠµ Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š¹ ŠæŠµŃŠ»Šø (ipv4) +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="166"/> + <source>NAT Networks: + +</source> + <translation>Š”ŠµŃŠø NAT: + +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="198"/> + <source>%zu %s found +</source> + <translation>ŠŠ°Š¹Š“ŠµŠ½Š¾ %zu %s +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="198"/> + <source>network</source> + <translation>ŃŠµŃŃ</translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageNATNetwork.cpp" line="198"/> + <source>networks</source> + <translation> + <numerusform>ŃŠµŃŃ</numerusform> + <numerusform>ŃŠµŃŠø</numerusform> + <numerusform>ŃŠµŃŠµŠ¹</numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="206"/> + <location filename="../VBoxManageNATNetwork.cpp" line="602"/> + <source>Not enough parameters</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="261"/> + <source>You can only specify --netname only once.</source> + <translation>--netname Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="267"/> + <source>You can only specify --network only once.</source> + <translation>--network Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="273"/> + <location filename="../VBoxManageNATNetwork.cpp" line="279"/> + <source>You can specify either --enable or --disable once.</source> + <translation>--enable Šø --disable Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="285"/> + <source>You can specify --dhcp only once.</source> + <translation>--dhcp Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="291"/> + <source>You can specify --ipv6 only once.</source> + <translation>--ipv6 Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="297"/> + <source>You can specify --ipv6-prefix only once.</source> + <translation>--ipv6-prefix Š¼Š¾Š¶Š½Š¾ ŃŠŗŠ°Š·Š°ŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š·.</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="303"/> + <source>You can specify --ipv6-default only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="313"/> + <source>loopback couldn't be deleted on modified +</source> + <translation>ŠŠ¾ŠŗŠ°Š»ŃŠ½Š°Ń ŠæŠµŃŠ»Ń Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŃŠ“Š°Š»ŠµŠ½Š° ŠøŠ»Šø ŠøŠ·Š¼ŠµŠ½ŠµŠ½Š° +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="324"/> + <location filename="../VBoxManageNATNetwork.cpp" line="362"/> + <source>Not enough parŠ°meters +</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š² +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="349"/> + <source>Invalid port-forward rule %s +</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠæŃŠ°Š²ŠøŠ»Š¾ ŠæŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠæŠ¾ŃŃŠ¾Š² %s +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="357"/> + <source>Port-forward could be deleted on modify +</source> + <translation>ŠŃŠ°Š²ŠøŠ»Š¾ ŠæŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠæŠ¾ŃŃŠ¾Š² Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŃŠ“Š°Š»ŠµŠ½Š¾ ŠæŃŠø ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŠø +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="365"/> + <source>Port-forward rule name is too long +</source> + <translation>ŠŠ¼Ń ŠæŃŠ°Š²ŠøŠ»Š° ŠæŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠæŠ¾ŃŃŠ¾Š² ŃŠ»ŠøŃŠŗŠ¾Š¼ Š±Š¾Š»ŃŃŠ¾Šµ +</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="382"/> + <source>You need to specify the --netname option</source> + <translation>ŠŠµŠ¾Š±Ń
Š¾Š“ŠøŠ¼Š¾ ŃŠŗŠ°Š·Š°ŃŃ Š¾ŠæŃŠøŃ --netname</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="388"/> + <source>You need to specify the --network option</source> + <translation>ŠŠµŠ¾Š±Ń
Š¾Š“ŠøŠ¼Š¾ ŃŠŗŠ°Š·Š°ŃŃ Š¾ŠæŃŠøŃ --network</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="396"/> + <source>Unknown operation (:%d)</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŠµŃŠ°ŃŠøŃ (:%d)</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="408"/> + <source>NATNetwork server already exists</source> + <translation>Š”ŠµŃŠ²ŠµŃ ŃŠµŃŠø NAT ŃŠ¶Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="412"/> + <source>Failed to create the NAT network service</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ ŃŠ»ŃŠ¶Š±Ń ŃŠµŃŠø NAT</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="415"/> + <source>NATNetwork server does not exist</source> + <translation>Š”ŠµŃŠ²ŠµŃ ŃŠµŃŠø NAT Š½Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="426"/> + <location filename="../VBoxManageNATNetwork.cpp" line="432"/> + <location filename="../VBoxManageNATNetwork.cpp" line="444"/> + <location filename="../VBoxManageNATNetwork.cpp" line="451"/> + <location filename="../VBoxManageNATNetwork.cpp" line="462"/> + <location filename="../VBoxManageNATNetwork.cpp" line="470"/> + <location filename="../VBoxManageNATNetwork.cpp" line="565"/> + <source>Failed to set configuration</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŠŗŠ¾Š½ŃŠøŠ³ŃŃŠ°ŃŠøŃ</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="481"/> + <source>Failed to delete pf</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ ŠæŃŠ°Š²ŠøŠ»Š¾ ŠæŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠæŠ¾ŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="506"/> + <source>Failed to add pf</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š“Š¾Š±Š°Š²ŠøŃŃ ŠæŃŠ°Š²ŠøŠ»Š¾ ŠæŠµŃŠµŠ½Š°ŠæŃŠ°Š²Š»ŠµŠ½ŠøŃ ŠæŠ¾ŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="532"/> + <location filename="../VBoxManageNATNetwork.cpp" line="538"/> + <source>invalid loopback string</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŃŃŃŠ¾ŠŗŠ° Š»Š¾ŠŗŠ°Š»ŃŠ½Š¾Š¹ ŠæŠµŃŠ»Šø</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="573"/> + <source>Failed to remove nat network</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“Š°Š»ŠøŃŃ ŃŠµŃŃ NAT</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="580"/> + <source>Failed to start network</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°ŠæŃŃŃŠøŃŃ ŃŠµŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="587"/> + <source>Failed to stop network</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š¾ŃŃŠ°Š½Š¾Š²ŠøŃŃ ŃŠµŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="636"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> +</context> +<context> + <name>Nvram</name> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="121"/> + <source>No platform key file path was given to "enrollpk"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŠæŃŃŃ Šŗ ŃŠ°Š¹Š»Ń Ń ŠŗŠ»ŃŃŠ¾Š¼ ŠæŠ»Š°ŃŃŠ¾ŃŠ¼Ń Š“Š»Ń "enrollpk"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="123"/> + <source>No owner UUID was given to "enrollpk"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ UUID Š²Š»Š°Š“ŠµŠ»ŃŃŠ° Š“Š»Ń "enrollpk"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="147"/> + <source>Cannot read contents of file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŃŠ¾ŃŠµŃŃŃ ŃŠ¾Š“ŠµŃŠ¶ŠøŠ¼Š¾Šµ ŃŠ°Š¹Š»Š° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="150"/> + <source>File "%s" is bigger than 32KByte</source> + <translation>Š¤Š°Š¹Š» "%s" Š±Š¾Š»ŃŃŠµ 32 ŠŠŠ°Š¹Ń</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="153"/> + <source>Cannot get size of file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ ŠæŠ¾Š»ŃŃŠøŃŃ ŃŠ°Š·Š¼ŠµŃ ŃŠ°Š¹Š»Š° "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="158"/> + <source>Cannot open file "%s": %Rrc</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š¾ŃŠŗŃŃŃŃ ŃŠ°Š¹Š» "%s": %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="250"/> + <source>No variable name was given to "queryvar"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠæŠµŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“Š»Ń "queryvar"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="277"/> + <source>Error writing to '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø Š·Š°ŠæŠøŃŠø Š² '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="282"/> + <location filename="../VBoxManageModifyNvram.cpp" line="411"/> + <source>Error opening '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø Š¾ŃŠŗŃŃŃŠøŠø '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="329"/> + <source>No variable name was given to "deletevar"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠæŠµŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“Š»Ń "deletevar"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="331"/> + <source>No owner UUID was given to "deletevar"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ UUID Š²Š»Š°Š“ŠµŠ»ŃŃŠ° Š“Š»Ń "deletevar"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="381"/> + <source>No variable name was given to "changevar"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠæŠµŃŠµŠ¼ŠµŠ½Š½Š¾Š¹ Š“Š»Ń "changevar"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="383"/> + <source>No variable data filename was given to "changevar"</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŃŠ°Š¹Š»Š° Ń Š“Š°Š½Š½ŃŠ¼Šø Š“Š»Ń "changevar"</translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="407"/> + <source>Error reading from '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŠæŃŠø ŃŃŠµŠ½ŠøŠø ŠøŠ· '%s': %Rrc</translation> + </message> +</context> +<context> + <name>Snapshot</name> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="198"/> + <location filename="../VBoxManageSnapshot.cpp" line="520"/> + <location filename="../VBoxManageSnapshot.cpp" line="594"/> + <source>This machine does not have any snapshots +</source> + <translation>Š£ ŃŃŠ¾Š¹ Š¼Š°ŃŠøŠ½Ń Š½ŠµŃ ŃŠ½ŠøŠ¼ŠŗŠ¾Š² +</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="254"/> + <source>[%RI32] Images and snapshots for medium "%ls" +</source> + <translation>[%RI32] ŠŠ±ŃŠ°Š·Ń Šø ŃŠ½ŠøŠ¼ŠŗŠø Š½Š¾ŃŠøŃŠµŠ»Ń "%ls" +</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="329"/> + <source>Not enough parameters</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="359"/> + <location filename="../VBoxManageSnapshot.cpp" line="561"/> + <source>Missing snapshot name</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ ŠøŠ¼Ń ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="404"/> + <source>Invalid unique name description '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š¾ŠæŠøŃŠ°Š½ŠøŠµ ŃŠ½ŠøŠŗŠ°Š»ŃŠ½Š¾Š³Š¾ ŠøŠ¼ŠµŠ½Šø '%s'</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="467"/> + <source>Failed to generate a unique snapshot name</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ³ŠµŠ½ŠµŃŠøŃŠ¾Š²Š°ŃŃ ŃŠ½ŠøŠŗŠ°Š»ŃŠ½Š¾Šµ ŠøŠ¼Ń ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="483"/> + <source>Snapshot taken. UUID: %ls +</source> + <translation>Š”Š½ŠøŠ¼Š¾Šŗ ŃŠ“ŠµŠ»Š°Š½. UUID: %ls +</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="485"/> + <source>Failed to take snapshot</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ“ŠµŠ»Š°ŃŃ ŃŠ½ŠøŠ¼Š¾Šŗ</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="500"/> + <source>Too many arguments</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š½Š¾Š³Š¾ Š°ŃŠ³ŃŠ¼ŠµŠ½ŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="508"/> + <location filename="../VBoxManageSnapshot.cpp" line="628"/> + <source>Expecting snapshot name only</source> + <translation>ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŃŠ¾Š»ŃŠŗŠ¾ ŠøŠ¼Ń ŃŠ½ŠøŠ¼ŠŗŠ°</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="539"/> + <source>%s snapshot '%ls' (%ls) +</source> + <translation>%s ŃŠ½ŠøŠ¼ŠŗŠ° '%ls' (%ls) +</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="540"/> + <source>Deleting</source> + <translation>Š£Š“Š°Š»ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="540"/> + <source>Restoring</source> + <translation>ŠŠ¾ŃŃŃŠ°Š½Š¾Š²Š»ŠµŠ½ŠøŠµ</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="554"/> + <source>Snapshot operation failed</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾Š²ŠµŃŃŠø Š¾ŠæŠµŃŠ°ŃŠøŃ Š½Š°Š“ ŃŠ½ŠøŠ¼ŠŗŠ¾Š¼</translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="652"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> +</context> +<context> + <name>Storage</name> + <message> + <location filename="../VBoxManageStorageController.cpp" line="166"/> + <location filename="../VBoxManageStorageController.cpp" line="1180"/> + <source>Invalid --type argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --type '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="305"/> + <source>Invalid medium type '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŃŠøŠæ Š½Š¾ŃŠøŃŠµŠ»Ń '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="327"/> + <source>Storage controller name not specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ° Š½Š¾ŃŠøŃŠµŠ»ŠµŠ¹</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="347"/> + <source>Drive passthrough state cannot be changed while the VM is running +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ ŠæŃŃŠ¼Š¾Š³Š¾ Š“Š¾ŃŃŃŠæŠ° Šŗ Š“ŠøŃŠŗŃ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½Š¾ ŠæŠ¾ŠŗŠ° ŃŠ°Š±Š¾ŃŠ°ŠµŃ ŠŠ +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="349"/> + <source>Bandwidth group cannot be changed while the VM is running +</source> + <translation>ŠŃŃŠæŠæ ŠæŠ¾Š»Š¾ŃŃ ŠæŃŠ¾ŠæŃŃŠŗŠ°Š½ŠøŃ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ ŠøŠ·Š¼ŠµŠ½ŠµŠ½Š° ŠæŠ¾ŠŗŠ° ŃŠ°Š±Š¾ŃŠ°ŠµŃ ŠŠ +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="356"/> + <source>Could not find a controller named '%s' +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="370"/> + <source>Port not specified</source> + <translation>ŠŠ¾ŃŃ Š½Šµ ŃŠŗŠ°Š·Š°Š½</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="377"/> + <source>Device not specified</source> + <translation>Š£ŃŃŃŠ¾Š¹ŃŃŠ²Š¾ Š½Šµ ŃŠŗŠ°Š·Š°Š½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="441"/> + <source>No DVD/Floppy Drive attached to the controller '%s'at the port: %u, device: %u</source> + <translation>ŠŠ° ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ '%s' ŠæŠ¾ŃŃ %u ŃŃŃŃŠ¾Š¹ŃŃŠ²Š¾: %u Š½Šµ ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½Š¾ ŠŗŠ°ŠŗŠøŃ
Š»ŠøŠ±Š¾ DVD ŠøŠ»Šø Š¤Š»Š¾ŠæŠæŠø Š“ŠøŃŠŗŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="461"/> + <source>The attachment is not supported by the storage controller '%s'</source> + <translation>ŠŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŠµ Š“Š°Š½Š½Š¾Š³Š¾ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š° Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š¼ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="516"/> + <source>Cannot find the Guest Additions ISO image +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ISO Š¾Š±ŃŠ°Š· ŠŠ¾ŠæŠ¾Š»Š½ŠµŠ½ŠøŠ¹ ŠŠ¾ŃŃŠµŠ²Š¾Š¹ ŠŠ” +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="542"/> + <source>Argument --type must be specified +</source> + <translation>ŠŃŠ³ŃŠ¼ŠµŠ½Ń --type Š“Š¾Š»Š¶ŠµŠ½ Š±ŃŃŃ ŃŠŗŠ°Š·Š°Š½ +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="556"/> + <source>The given attachment is not supported by the storage controller '%s'</source> + <translation>Š£ŠŗŠ°Š·Š°Š½Š½Š¾Šµ ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŠµ ŃŃŃŃŠ¾Š¹ŃŃŠ²Š° Š½Šµ ŠæŠ¾Š“Š“ŠµŃŠ¶ŠøŠ²Š°ŠµŃŃŃ ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ¾Š¼ Š½Š¾ŃŠøŃŠµŠ»ŠµŠ¹ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="578"/> + <location filename="../VBoxManageStorageController.cpp" line="582"/> + <source>Invalid host DVD drive name "%s"</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń DVD Š“ŠøŃŠŗŠ¾Š²Š¾Š“Š° Ń
Š¾ŃŃŠ° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="591"/> + <source>Invalid host floppy drive name "%s"</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠøŠ¼Ń ŃŠ»Š¾ŠæŠæŠø Š“ŠøŃŠŗŠ¾Š²Š¾Š“Š° Ń
Š¾ŃŃŠ° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="598"/> + <source>Parameters --server and --target are required for iSCSI media</source> + <translation>ŠŠ»Ń iSCSI Š½Š¾ŃŠøŃŠµŠ»ŠµŠ¹ ŃŃŠµŠ±ŃŃŃŃŃ ŠæŠ°ŃŠ°Š¼ŠµŃŃŃ --server Šø --target</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="665"/> + <source>iSCSI disk created. UUID: %s +</source> + <translation>Š”Š¾Š·Š“Š°Š½ iSCSI Š“ŠøŃŠŗ. UUID: %s +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="676"/> + <source>Missing --medium argument</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń --medium</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="685"/> + <source>Invalid UUID or filename "%s"</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ UUID ŠøŠ»Šø ŠøŠ¼Ń ŃŠ°Š¹Š»Š° "%s"</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="695"/> + <source>Failed to set the medium/parent medium UUID</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ UUID Š½Š¾ŃŠøŃŠµŠ»Ń ŠøŠ»Šø UUID ŃŠ¾Š“ŠøŃŠµŠ»ŃŃŠŗŠ¾Š³Š¾ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="709"/> + <source>Failed to set the medium type</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ Š·Š°Š“Š°ŃŃ ŃŠøŠæ Š½Š¾ŃŠøŃŠµŠ»Ń</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="804"/> + <source>Invalid --passthrough argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --passthrough '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="807"/> + <location filename="../VBoxManageStorageController.cpp" line="833"/> + <location filename="../VBoxManageStorageController.cpp" line="859"/> + <location filename="../VBoxManageStorageController.cpp" line="885"/> + <location filename="../VBoxManageStorageController.cpp" line="911"/> + <source>Couldn't find the controller attachment for the controller '%s' +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠæŠ¾Š“ŠŗŠ»ŃŃŠµŠ½ŠøŠµ Šŗ ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŃ '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="830"/> + <source>Invalid --tempeject argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --tempeject '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="856"/> + <source>Invalid --nonrotational argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --nonrotational '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="882"/> + <source>Invalid --discard argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --discard '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="908"/> + <source>Invalid --hotpluggable argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --hotpluggable '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="990"/> + <source>Too few parameters</source> + <translation>Š”Š»ŠøŃŠŗŠ¾Š¼ Š¼Š°Š»Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1056"/> + <source>Storage controller name not specified +</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½Š¾ ŠøŠ¼Ń ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃŠ° Š½Š¾ŃŠøŃŠµŠ»ŠµŠ¹ +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1119"/> + <source>Invalid --add argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --add '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1186"/> + <location filename="../VBoxManageStorageController.cpp" line="1205"/> + <location filename="../VBoxManageStorageController.cpp" line="1236"/> + <location filename="../VBoxManageStorageController.cpp" line="1262"/> + <location filename="../VBoxManageStorageController.cpp" line="1281"/> + <source>Couldn't find the controller with the name: '%s' +</source> + <translation>ŠŠµŠ²Š¾Š·Š¼Š¾Š¶Š½Š¾ Š½Š°Š¹ŃŠø ŠŗŠ¾Š½ŃŃŠ¾Š»Š»ŠµŃ Ń ŠøŠ¼ŠµŠ½ŠµŠ¼ '%s' +</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1230"/> + <source>Invalid --hostiocache argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --hostiocache '%s'</translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1256"/> + <source>Invalid --bootable argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --bootable '%s'</translation> + </message> +</context> +<context> + <name>UpdateCheck</name> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="81"/> + <source>Enabled: %s +</source> + <translation>ŠŠŗŠ»ŃŃŠµŠ½Š¾: %s +</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="82"/> + <source>yes</source> + <translation>Š“Š°</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="82"/> + <source>no</source> + <translation>Š½ŠµŃ</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="89"/> + <source>Count: %u +</source> + <translation>ŠŠ¾Š»ŠøŃŠµŃŃŠ²Š¾: %u +</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="99"/> + <source>Frequency: never +</source> + <translation>Š§Š°ŃŃŠ¾ŃŠ°: Š½ŠøŠŗŠ¾Š³Š“Š° +</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="101"/> + <source>Frequency: every day +</source> + <translation>Š§Š°ŃŃŠ¾ŃŠ°: ŠŗŠ°Š¶Š“ŃŠ¹ Š“ŠµŠ½Ń +</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="103"/> + <source>Frequency: every %u days +</source> + <translation>Š§Š°ŃŃŠ¾ŃŠ°: ŠŗŠ°Š¶Š“ŃŠ¹ %u Š“ŠµŠ½Ń +</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="112"/> + <source>Stable - new minor and maintenance releases</source> + <translation>Š”ŃŠ°Š±ŠøŠ»ŃŠ½ŃŠµ - Š½Š¾Š²ŃŠµ Š¼ŠøŠ½Š¾ŃŠ½ŃŠµ Šø ŠŗŠ¾ŃŃŠµŠŗŃŠøŃŃŃŃŠøŠµ ŃŠµŠ»ŠøŠ·Ń</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="116"/> + <source>All releases - new minor, maintenance, and major releases</source> + <translation>ŠŃŠµ ŃŠµŠ»ŠøŠ·Ń - Š½Š¾Š²ŃŠµ Š¼ŠøŠ½Š¾ŃŠ½ŃŠµ, ŠŗŠ¾ŃŃŠµŠŗŃŠøŃŃŃŃŠøŠµ Šø Š¼Š°Š¶Š¾ŃŠ½ŃŠµ ŃŠµŠ»ŠøŠ·Ń</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="120"/> + <source>With Betas - new minor, maintenance, major, and beta releases</source> + <translation>Š” Š±ŠµŃŠ°Š¼Šø - Š½Š¾Š²ŃŠµ Š¼ŠøŠ½Š¾ŃŠ½ŃŠµ, ŠŗŠ¾ŃŃŠµŠŗŃŠøŃŃŃŃŠøŠµ, Š¼Š°Š¶Š¾ŃŠ½ŃŠµ Šø Š±ŠµŃŠ° ŃŠµŠ»ŠøŠ·Ń</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="125"/> + <source>Unset</source> + <translation>ŠŠµ Š·Š°Š“Š°Š½Š¾</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="132"/> + <source>Channel: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="189"/> + <source>Unknown channel specified: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="258"/> + <source>Checking for a new %ls version... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="269"/> + <source>Failed to create update progress object: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="277"/> + <source>Checking for update failed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="296"/> + <source>A new version of %ls has been released! Version %ls is available at virtualbox.org. +You can download this version here: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="312"/> + <source>You are already running the most recent version of %ls. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="324"/> + <source>Something went wrong while checking for updates! +Please check network connection and try again later. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Target: %s +</source> + <translation type="vanished">Š¦ŠµŠ»Ń: %s +</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="140"/> + <source>Last Check Date: %ls +</source> + <translation>ŠŠ¾ŃŠ»ŠµŠ“Š½ŃŃ Š“Š°ŃŠ° ŠæŃŠ¾Š²ŠµŃŠŗŠø: %ls +</translation> + </message> + <message> + <source>Unknown target specified: '%s'</source> + <translation type="vanished">Š£ŠŗŠ°Š·Š°Š½Š° Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń ŃŠµŠ»Ń: '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="195"/> + <source>The update frequency cannot be zero</source> + <translation>Š§Š°ŃŃŠ¾ŃŠ° Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹ Š½Šµ Š¼Š¾Š¶ŠµŃ Š±ŃŃŃ Š½ŃŠ»ŠµŠ²Š¾Š¹</translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="206"/> + <source>No change requested</source> + <translation>ŠŠµ Š·Š°ŠæŃŠ¾ŃŠµŠ½Š¾ ŠøŠ·Š¼ŠµŠ½ŠµŠ½ŠøŠ¹</translation> + </message> + <message> + <source>Checking for a new VirtualBox version... +</source> + <translation type="vanished">ŠŃŠ¾Š²ŠµŃŠŗŠ° Š½Š° Š½Š°Š»ŠøŃŠøŠµ Š½Š¾Š²Š¾Š¹ Š²ŠµŃŃŠøŠø VirtualBox... +</translation> + </message> + <message> + <source>VirtualBox update checking has been disabled. +</source> + <translation type="vanished">ŠŃŠ¾Š²ŠµŃŠŗŠ° Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŠ¹ VirtualBox Š¾ŃŠŗŠ»ŃŃŠµŠ½Š°. +</translation> + </message> + <message> + <source>Failed to create ptrProgress object: %Rhrc +</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±ŃŠµŠŗŃ ptrProgress: %Rhrc +</translation> + </message> + <message> + <source>Check for update failed.</source> + <translation type="vanished">ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠ¾Š²ŠµŃŠøŃŃ Š¾Š±Š½Š¾Š²Š»ŠµŠ½ŠøŃ.</translation> + </message> + <message> + <source>A new version of VirtualBox has been released! Version %ls is available at virtualbox.org. +You can download this version here: %ls +</source> + <translation type="vanished">ŠŃŠæŃŃŠµŠ½Š° Š½Š¾Š²Š°Ń Š²ŠµŃŃŠøŃ VirtualBox! ŠŠµŃŃŠøŃ %ls Š“Š¾ŃŃŃŠæŠ½Š° Š½Š° ŃŠ°Š¹ŃŠµ virtualbox.org. +ŠŃ Š¼Š¾Š¶ŠµŃŠµ Š·Š°Š³ŃŃŠ·ŠøŃŃ ŃŃŃ Š²ŠµŃŃŠøŃ Š·Š“ŠµŃŃ: %ls +</translation> + </message> + <message> + <source>You are already running the most recent version of VirtualBox. +</source> + <translation type="vanished">ŠŃ ŃŠ¶Šµ ŠøŃŠæŠ¾Š»ŃŠ·ŃŠµŃŠµ ŠæŠ¾ŃŠ»ŠµŠ“Š½ŃŃ Š²ŠµŃŃŠøŃ VirtualBox. +</translation> + </message> +</context> +<context> + <name>Usb</name> + <message> + <location filename="../VBoxManageUSB.cpp" line="178"/> + <location filename="../VBoxManageUSB.cpp" line="214"/> + <location filename="../VBoxManageUSB.cpp" line="216"/> + <location filename="../VBoxManageUSB.cpp" line="373"/> + <location filename="../VBoxManageUSB.cpp" line="571"/> + <source>Not enough parameters</source> + <translation>ŠŠµŠ“Š¾ŃŃŠ°ŃŠ¾ŃŠ½Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="199"/> + <source>Invalid parameter '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="203"/> + <source>Invalid index '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠøŠ½Š“ŠµŠŗŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="231"/> + <location filename="../VBoxManageUSB.cpp" line="246"/> + <location filename="../VBoxManageUSB.cpp" line="254"/> + <location filename="../VBoxManageUSB.cpp" line="267"/> + <location filename="../VBoxManageUSB.cpp" line="275"/> + <location filename="../VBoxManageUSB.cpp" line="283"/> + <location filename="../VBoxManageUSB.cpp" line="291"/> + <location filename="../VBoxManageUSB.cpp" line="299"/> + <location filename="../VBoxManageUSB.cpp" line="307"/> + <location filename="../VBoxManageUSB.cpp" line="315"/> + <location filename="../VBoxManageUSB.cpp" line="323"/> + <location filename="../VBoxManageUSB.cpp" line="336"/> + <location filename="../VBoxManageUSB.cpp" line="381"/> + <source>Missing argument to '%s'</source> + <translation>ŠŃŃŃŃŃŃŠ²ŃŠµŃ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="261"/> + <source>Invalid --active argument '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ Š°ŃŠ³ŃŠ¼ŠµŠ½Ń Šŗ --active '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="328"/> + <source>Failed to convert the --maskedinterfaces value '%s' to a number, vrc=%Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŃŠµŠ¾Š±ŃŠ°Š·Š¾Š²Š°ŃŃ Š·Š½Š°ŃŠµŠ½ŠøŠµ --maskedinterfaces '%s' Š² ŃŠøŃŠ»Š¾, vrc=%Rrc</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="343"/> + <source>Invalid USB filter action '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ Š“ŠµŠ¹ŃŃŠ²ŠøŠµ USB ŃŠøŠ»ŃŃŃŠ° '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="346"/> + <source>Unknown option '%s'</source> + <translation>ŠŠµŠøŠ·Š²ŠµŃŃŠ½Š°Ń Š¾ŠæŃŠøŃ '%s'</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="363"/> + <location filename="../VBoxManageUSB.cpp" line="395"/> + <source>Mandatory options not supplied</source> + <translation>ŠŠµ ŠæŃŠµŠ“Š¾ŃŃŠ°Š²Š»ŠµŠ½Ń Š¾Š±ŃŠ·Š°ŃŠµŠ»ŃŠ½ŃŠµ Š¾ŠæŃŠøŠø</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="581"/> + <source>Invalid number of parameters</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š¾Šµ ŠŗŠ¾Š»ŠøŃŠµŃŃŠ²Š¾ ŠæŠ°ŃŠ°Š¼ŠµŃŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="596"/> + <source>Parameter "%s" is invalid</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼ŃŠ¹ ŠæŠ°ŃŠ°Š¼ŠµŃŃ '%s'</translation> + </message> +</context> +<context> + <name>Utils</name> + <message> + <location filename="../VBoxManageUtils.cpp" line="102"/> + <source>type bridged</source> + <translation>ŃŠøŠæŠ° ŃŠµŃŠµŠ²Š¾Š¹ Š¼Š¾ŃŃ</translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="106"/> + <source>type host-only</source> + <translation>ŃŠøŠæŠ° Š²ŠøŃŃŃŠ°Š»ŃŠ½Š°Ń ŃŠµŃŃ Ń
Š¾ŃŃŠ°</translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="111"/> + <source>unknown type %RU32</source> + <translation>Š½ŠµŠøŠ·Š²ŠµŃŃŠ½Š¾Š³Š¾ ŃŠøŠæŠ° %RU32</translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="116"/> + <source>Interface "%s" is of %s</source> + <translation>ŠŠ½ŃŠµŃŃŠµŠ¹Ń "%s" %s</translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="120"/> + <source>Interface "%s" doesn't seem to exist</source> + <translation>ŠŠ°Š¶ŠµŃŃŃ, ŠøŠ½ŃŠµŃŃŠµŠ¹Ń "%s" Š½Šµ ŃŃŃŠµŃŃŠ²ŃŠµŃ</translation> + </message> +</context> +<context> + <name>VBoxManage</name> + <message> + <location filename="../VBoxManage.cpp" line="327"/> + <location filename="../VBoxManage.cpp" line="495"/> + <source>Progress object failure: %Rhrc +</source> + <translation>ŠŃŠŗŠ°Š· Š¾Š±ŃŠµŠŗŃŠ° ŠæŃŠ¾Š³ŃŠµŃŃŠ°: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="344"/> + <source>Failed to get progress description: %Rhrc +</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠæŠ¾Š»ŃŃŠøŃŃ Š¾ŠæŠøŃŠ°Š½ŠøŠµ ŠæŃŠ¾Š³ŃŠµŃŃŠ°: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="411"/> + <source>(%u/%u) %ls %02u%% => %02u%% (%d s remaining) +</source> + <translation>(%u/%u) %ls %02u%% => %02u%% (%d ŃŠµŠŗ Š¾ŃŃŠ°Š»Š¾ŃŃ) +</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="481"/> + <source>CANCELED +</source> + <translation>ŠŠ¢ŠŠŠŠŠŠ +</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="485"/> + <source>Progress state: %Rhrc +</source> + <translation>Š”Š¾ŃŃŠ¾ŃŠ½ŠøŠµ ŠæŃŠ¾Š³ŃŠµŃŃŠ°: %Rhrc +</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="672"/> + <source>Password expected</source> + <translation>ŠŠ¶ŠøŠ“Š°ŠµŃŃŃ ŠæŠ°ŃŠ¾Š»Ń</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="680"/> + <source>No password file specified</source> + <translation>ŠŠµ ŃŠŗŠ°Š·Š°Š½ ŃŠ°Š¹Š» Ń ŠæŠ°ŃŠ¾Š»ŠµŠ¼</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="687"/> + <source>Only one response file allowed</source> + <translation>Š Š°Š·ŃŠµŃŠ°ŠµŃŃŃ ŃŠ¾Š»ŃŠŗŠ¾ Š¾Š“ŠøŠ½ ŃŠ°Š¹Š» Š¾ŃŠ²ŠµŃŠ¾Š²</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="695"/> + <source>Error reading response file '%s': %Rrc</source> + <translation>ŠŃŠøŠ±ŠŗŠ° ŃŃŠµŠ½ŠøŃ ŃŠ°Š¹Š»Š° Š¾ŃŠ²ŠµŃŠ¾Š² '%s': %Rrc</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="700"/> + <source>Invalid response file ('%s') encoding: %Rrc</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠŗŠ¾Š“ŠøŃŠ¾Š²ŠŗŠ° ŃŠ°Š¹Š»Š° Š¾ŃŠ²ŠµŃŠ¾Š² ('%s'): %Rrc</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="708"/> + <source>Failed to parse response file '%s' (bourne shell style): %Rrc</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ°Š·Š¾Š±ŃŠ°ŃŃ ŃŠ°Š¹Š» Š¾ŃŠ²ŠµŃŠ¾Š² '%s' (ŃŃŠøŠ»Ń bourne shell): %Rrc</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="714"/> + <source>out of memory</source> + <translation>Š½Šµ Ń
Š²Š°ŃŠ°ŠµŃ ŠæŠ°Š¼ŃŃŠø</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="755"/> + <source>commands: +</source> + <translation>ŠŗŠ¾Š¼Š°Š½Š“Ń: +</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="762"/> + <source>Invalid command '%s'</source> + <translation>ŠŠµŠ“Š¾ŠæŃŃŃŠøŠ¼Š°Ń ŠŗŠ¾Š¼Š°Š½Š“Š° '%s'</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="781"/> + <source>Failed to initialize COM because the global settings directory '%s' is not accessible!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·ŠøŃŠ¾Š²Š°ŃŃ COM, ŠæŠ¾ŃŠ¾Š¼Ń ŃŃŠ¾ Š“ŠøŃŠµŠŗŃŠ¾ŃŠøŃ Š³Š»Š¾Š±Š°Š»ŃŠ½ŃŃ
Š½Š°ŃŃŃŠ¾ŠµŠŗ '%s' Š½ŠµŠ“Š¾ŃŃŃŠæŠ½Š°!</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="784"/> + <source>Failed to initialize COM! (hrc=%Rhrc)</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŠøŠ½ŠøŃŠøŠ°Š»ŠøŠ·ŠøŃŠ¾Š²Š°ŃŃ COM! (hrc=%Rhrc)</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="867"/> + <source>Failed to create a session object!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±ŃŠµŠŗŃ ŃŠµŃŃŠøŠø!</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="877"/> + <source>Failed to create the VirtualBox object!</source> + <translation>ŠŠµ ŃŠ“Š°Š»Š¾ŃŃ ŃŠ¾Š·Š“Š°ŃŃ Š¾Š±ŃŠµŠŗŃ VirtualBox!</translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="881"/> + <source>Most likely, the VirtualBox COM server is not running or failed to start.</source> + <translation>ŠŠ°ŠøŠ±Š¾Š»ŠµŠµ Š²ŠµŃŠ¾ŃŃŠ½Š¾, ŃŃŠ¾ COM ŃŠµŃŠ²ŠµŃ VirtualBox Š½Šµ Š·Š°ŠæŃŃŠµŠ½ ŠøŠ»Šø Š½Šµ ŃŠ¼Š¾Š³ Š·Š°ŠæŃŃŃŠøŃŃŃŃ.</translation> + </message> +</context> +</TS> diff --git a/src/VBox/Frontends/VBoxManage/nls/VBoxManageNls_xx_YY.ts b/src/VBox/Frontends/VBoxManage/nls/VBoxManageNls_xx_YY.ts new file mode 100644 index 00000000..d3e72f7b --- /dev/null +++ b/src/VBox/Frontends/VBoxManage/nls/VBoxManageNls_xx_YY.ts @@ -0,0 +1,10640 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1"> +<context> + <name>Appliance</name> + <message> + <location filename="../VBoxManageAppliance.cpp" line="256"/> + <location filename="../VBoxManageAppliance.cpp" line="1551"/> + <source>Option "%s" can't be used together with "--cloud" option.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="259"/> + <location filename="../VBoxManageAppliance.cpp" line="334"/> + <location filename="../VBoxManageAppliance.cpp" line="1554"/> + <location filename="../VBoxManageAppliance.cpp" line="1637"/> + <source>Value of option "%s" is out of range.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="268"/> + <location filename="../VBoxManageAppliance.cpp" line="275"/> + <location filename="../VBoxManageAppliance.cpp" line="289"/> + <location filename="../VBoxManageAppliance.cpp" line="303"/> + <location filename="../VBoxManageAppliance.cpp" line="317"/> + <location filename="../VBoxManageAppliance.cpp" line="324"/> + <location filename="../VBoxManageAppliance.cpp" line="1562"/> + <source>Option "%s" requires preceding --vsys or --cloud option.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="282"/> + <location filename="../VBoxManageAppliance.cpp" line="296"/> + <location filename="../VBoxManageAppliance.cpp" line="310"/> + <location filename="../VBoxManageAppliance.cpp" line="331"/> + <location filename="../VBoxManageAppliance.cpp" line="342"/> + <location filename="../VBoxManageAppliance.cpp" line="352"/> + <location filename="../VBoxManageAppliance.cpp" line="362"/> + <location filename="../VBoxManageAppliance.cpp" line="372"/> + <location filename="../VBoxManageAppliance.cpp" line="382"/> + <location filename="../VBoxManageAppliance.cpp" line="1569"/> + <location filename="../VBoxManageAppliance.cpp" line="1576"/> + <location filename="../VBoxManageAppliance.cpp" line="1583"/> + <location filename="../VBoxManageAppliance.cpp" line="1590"/> + <location filename="../VBoxManageAppliance.cpp" line="1597"/> + <location filename="../VBoxManageAppliance.cpp" line="1604"/> + <location filename="../VBoxManageAppliance.cpp" line="1611"/> + <location filename="../VBoxManageAppliance.cpp" line="1618"/> + <source>Option "%s" requires preceding --vsys option.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="345"/> + <location filename="../VBoxManageAppliance.cpp" line="355"/> + <location filename="../VBoxManageAppliance.cpp" line="365"/> + <location filename="../VBoxManageAppliance.cpp" line="375"/> + <location filename="../VBoxManageAppliance.cpp" line="385"/> + <source>Option "%s" requires preceding --unit option.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="392"/> + <source>Invalid import options '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="401"/> + <location filename="../VBoxManageAppliance.cpp" line="1634"/> + <source>Option "%s" can't be used together with "--vsys" option.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="410"/> + <location filename="../VBoxManageAppliance.cpp" line="417"/> + <location filename="../VBoxManageAppliance.cpp" line="424"/> + <location filename="../VBoxManageAppliance.cpp" line="1646"/> + <location filename="../VBoxManageAppliance.cpp" line="1653"/> + <location filename="../VBoxManageAppliance.cpp" line="1660"/> + <location filename="../VBoxManageAppliance.cpp" line="1667"/> + <location filename="../VBoxManageAppliance.cpp" line="1674"/> + <location filename="../VBoxManageAppliance.cpp" line="1681"/> + <location filename="../VBoxManageAppliance.cpp" line="1688"/> + <location filename="../VBoxManageAppliance.cpp" line="1695"/> + <location filename="../VBoxManageAppliance.cpp" line="1702"/> + <location filename="../VBoxManageAppliance.cpp" line="1709"/> + <location filename="../VBoxManageAppliance.cpp" line="1716"/> + <location filename="../VBoxManageAppliance.cpp" line="1723"/> + <location filename="../VBoxManageAppliance.cpp" line="1730"/> + <source>Option "%s" requires preceding --cloud option.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="433"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="440"/> + <source>Invalid option -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="442"/> + <source>Invalid option case %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="445"/> + <source>unknown option: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="449"/> + <source>error: %Rrs</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="455"/> + <source>Not enough arguments for "import" command.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="477"/> + <source>Not enough arguments for import from the Cloud.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="500"/> + <source>Appliance read failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="512"/> + <source>Interpreting %ls... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="544"/> + <source>Disks: +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="565"/> + <source>Invalid index %RI32 with -vsys option; the OVF contains only %zu virtual system(s).</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="600"/> + <source>Virtual system %u: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="630"/> + <source>%2u: OS type specified with --ostype: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="634"/> + <source>%2u: Suggested OS type: "%ls" + (change with "--vsys %u --ostype <type>"; use "list ostypes" to list all possible values) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="643"/> + <source>%2u: VM name specified with --vmname: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="647"/> + <source>%2u: Suggested VM name "%ls" + (change with "--vsys %u --vmname <name>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="653"/> + <source>%2u: Product (ignored): %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="658"/> + <source>%2u: ProductUrl (ignored): %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="663"/> + <source>%2u: Vendor (ignored): %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="668"/> + <source>%2u: VendorUrl (ignored): %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="673"/> + <source>%2u: Version (ignored): %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="681"/> + <source>%2u: Description specified with --description: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="685"/> + <source>%2u: Description "%ls" + (change with "--vsys %u --description <desc>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="696"/> + <source>%2u: End-user license agreement + (accept with "--vsys %u --eula accept"): + +%ls + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="703"/> + <source>%2u: End-user license agreement (accepted) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="708"/> + <source>Argument to --eula must be either "show" or "accept".</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="711"/> + <source>%2u: End-user license agreement + (display with "--vsys %u --eula show"; + accept with "--vsys %u --eula accept") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="727"/> + <source>%2u: No. of CPUs specified with --cpus: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="731"/> + <source>Argument to --cpus option must be a number greater than %d and less than %d.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="735"/> + <source>%2u: Number of CPUs: %ls + (change with "--vsys %u --cpus <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="747"/> + <source>%2u: Guest memory specified with --memory: %ls MB +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="751"/> + <source>Argument to --memory option must be a non-negative number.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="754"/> + <source>%2u: Guest memory: %ls MB + (change with "--vsys %u --memory <MB>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="762"/> + <source>%2u: IDE controller, type %ls -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="768"/> + <source>%2u: IDE controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="778"/> + <source>%2u: SATA controller, type %ls -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="784"/> + <source>%2u: SATA controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="794"/> + <source>%2u: SAS controller, type %ls -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="800"/> + <source>%2u: SAS controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="810"/> + <source>%2u: SCSI controller, type %ls -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="821"/> + <source>%2u: SCSI controller, type set with --unit %u --scsitype: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="827"/> + <source>%2u: SCSI controller, type %ls + (change with "--vsys %u --unit %u --scsitype {BusLogic|LsiLogic}"; + disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="839"/> + <source>%2u: VirtioSCSI controller, type %ls -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="845"/> + <source>%2u: VirtioSCSI controller, type %ls + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="855"/> + <source>%2u: Hard disk image: source image=%ls -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="870"/> + <source>Option --ImportToVDI can not be used together with a manually set target path.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="898"/> + <source>Invalid controller value: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="903"/> + <location filename="../VBoxManageAppliance.cpp" line="970"/> + <source>Invalid storage controller specified: %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="916"/> + <source>Invalid port value: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="931"/> + <source>Failed to extract controller value from ExtraConfig: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="937"/> + <source>Failed to extract channel value from ExtraConfig: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="963"/> + <source>Device already attached to controller %u at this port (%u) location.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1001"/> + <source>Illegal port value: %u. For %ls controllers the only valid values are 0 to %lu (inclusive)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1023"/> + <source>%2u: Hard disk image specified with --disk: source image=%ls, target path=%ls, %s + (change controller with "--vsys %u --unit %u --controller <index>"; + change controller port with "--vsys %u --unit %u --port <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1035"/> + <source>%2u: Hard disk image specified with --disk and --controller: source image=%ls, target path=%ls, %s + (change controller port with "--vsys %u --unit %u --port <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1045"/> + <source>%2u: Hard disk image specified with --disk and --port: source image=%ls, target path=%ls, %s + (change controller with "--vsys %u --unit %u --controller <index>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1055"/> + <source>%2u: Hard disk image specified with --controller and --port: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1065"/> + <source>%2u: Hard disk image specified with --port: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path"; + change controller with "--vsys %u --unit %u --controller <index>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1077"/> + <source>%2u: Hard disk image specified with --controller: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path"; + change controller port with "--vsys %u --unit %u --port <n>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1089"/> + <source>%2u: Hard disk image specified with --disk and --controller and --port: source image=%ls, target path=%ls, %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1174"/> + <source>%2u: Hard disk image: source image=%ls, target path=%ls, %s + (change target path with "--vsys %u --unit %u --disk path"; + change controller with "--vsys %u --unit %u --controller <index>"; + change controller port with "--vsys %u --unit %u --port <n>"; + disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1191"/> + <source>%2u: CD-ROM -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1196"/> + <source>%2u: CD-ROM + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1204"/> + <source>%2u: Floppy -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1209"/> + <source>%2u: Floppy + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1215"/> + <source>%2u: Network adapter: orig %ls, config %ls, extra %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1225"/> + <source>%2u: USB controller -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1230"/> + <source>%2u: USB controller + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1238"/> + <source>%2u: Sound card "%ls" -- disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1244"/> + <source>%2u: Sound card (appliance expects "%ls", can change on import) + (disable with "--vsys %u --unit %u --ignore") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1256"/> + <source>%2u: VM settings file name specified with --settingsfile: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1260"/> + <source>%2u: Suggested VM settings file name "%ls" + (change with "--vsys %u --settingsfile <filename>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1269"/> + <source>%2u: VM base folder specified with --basefolder: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1273"/> + <source>%2u: Suggested VM base folder "%ls" + (change with "--vsys %u --basefolder <path>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1282"/> + <source>%2u: VM group specified with --group: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1286"/> + <source>%2u: Suggested VM group "%ls" + (change with "--vsys %u --group <group>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1292"/> + <source>%2u: Suggested cloud shape "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1300"/> + <source>%2u: Cloud bucket id specified with --cloudbucket: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1304"/> + <source>%2u: Suggested cloud bucket id "%ls" + (change with "--cloud %u --cloudbucket <id>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1313"/> + <source>%2u: Cloud profile name specified with --cloudprofile: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1317"/> + <source>%2u: Suggested cloud profile name "%ls" + (change with "--cloud %u --cloudprofile <id>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1326"/> + <source>%2u: Cloud instance id specified with --cloudinstanceid: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1330"/> + <source>%2u: Suggested cloud instance id "%ls" + (change with "--cloud %u --cloudinstanceid <id>") +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1336"/> + <source>%2u: Suggested cloud base image id "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1384"/> + <source>Cannot import until the license agreement listed above is accepted.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1386"/> + <source>Cannot import until the %c license agreements listed above are accepted.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1397"/> + <source>Appliance import failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1400"/> + <source>Successfully imported the appliance. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1517"/> + <source>You can only specify --output once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1625"/> + <source>Invalid export options '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1751"/> + <source>unhandled option: -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1753"/> + <source>unhandled option: %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1756"/> + <source>unknown option: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1771"/> + <source>At least one machine must be specified with the export command.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1775"/> + <source>Missing --output argument with export command.</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="1789"/> + <source>Invalid index %RI32 with -vsys option; you specified only %zu virtual system(s).</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1878"/> + <source>Cannot read license file "%s" which should be included in the virtual system %u.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1941"/> + <source>Enter the passwords for the following identifiers to export the apppliance: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1948"/> + <source>Password ID %s:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="1978"/> + <source>Appliance write failed</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="1981"/> + <source>Successfully exported %d machine(s). +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2037"/> + <source>Creating a cloud instance... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2042"/> + <source>Creating the cloud instance failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2054"/> + <source>A cloud instance with id '%s' (provider '%s') was created +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2107"/> + <source>Failed to open OVA '%s' for updating: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2113"/> + <source>Failed to open OVA '%s' as a TAR file: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2120"/> + <source>Scanning OVA '%s' for a manifest and signature...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2136"/> + <source>RTVfsFsStrmNext returned %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2152"/> + <source>OVA contains multiple manifests! first: %s second: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2156"/> + <location filename="../VBoxManageAppliance.cpp" line="2194"/> + <source>Unsupported OVA file ordering! Signature file ('%s') as succeeded by '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2161"/> + <source>Found manifest file: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2170"/> + <source>Failed to memorize the manifest: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2173"/> + <location filename="../VBoxManageAppliance.cpp" line="2414"/> + <location filename="../VBoxManageAppliance.cpp" line="2488"/> + <location filename="../VBoxManageAppliance.cpp" line="2647"/> + <source>Out of memory!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2181"/> + <source>Multiple signature files! (%s)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2185"/> + <source>Found existing signature file: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2210"/> + <source>The OVA contains no manifest and cannot be signed!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2213"/> + <source>The OVA is already signed ('%s')! (Use the --force option to force re-signing it.)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2233"/> + <source>Writing '%s' to the OVA...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2243"/> + <source>RTZipTarFsStreamTruncate failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2252"/> + <source>RTVfsFileSeek(hVfsFileSignature) failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2258"/> + <source>RTVfsFsStrmAdd('%s') failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2265"/> + <source>RTVfsFsStrmEnd failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2301"/> + <source> Successfully decoded the PKCS#7/CMS signature...</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2317"/> + <source> Successfully verified the PKCS#7/CMS signature</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2320"/> + <source>Failed to verify the PKCS#7/CMS signature: %Rrc%RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2324"/> + <source>RTCrPkcs7SignedData_CheckSanity failed on PKCS#7/CMS signature: %Rrc%RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2329"/> + <source>PKCS#7/CMS signature inner ContentType isn't 'data' but: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2333"/> + <source>PKCS#7/CMD signature is not 'signedData': %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2374"/> + <source>RTCrPkcs7ContentInfo_Clone failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2378"/> + <source>RTCrPkcs7ContentInfo_DecodeAsn1 failed to decode PKCS#7/CMS signature: %Rrc%RTemi</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="2409"/> + <source>Manifest is too big: %#RX64 bytes, max 4MiB</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2434"/> + <source>RTCrStoreCertAddFromFile failed on '%s': %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2440"/> + <source>RTCrStoreCreateInMem failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="2471"/> + <source>Created PKCS#7/CMS signature: %zu bytes, %s.</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2474"/> + <source>Using SHA-1 instead of SHA-3 for the PKCS#7/CMS signature.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2483"/> + <source>RTCrPemWriteBlobToVfsFile failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2491"/> + <source>RTCrPkcs7SimpleSignSignedData failed: %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2495"/> + <source>RTVfsFileReadAt failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2548"/> + <source>Unsupported digest type: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2557"/> + <source>Failed to create digest for %s: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageAppliance.cpp" line="2583"/> + <source>Created OVA signature: %zu bytes, %s</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2596"/> + <source> Successfully decoded and verified the OVA signature. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2627"/> + <source>Failed to write certificate to signature file: %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2631"/> + <source>Failed to produce signature file: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2635"/> + <source>RTVfsMemFileCreate failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2638"/> + <source>Encountered a problem when validating the signature we just created: %Rrc%#RTeim +Please make sure the certificate and private key matches.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2643"/> + <source>2nd RTCrPkixPubKeySignDigest call failed: %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2650"/> + <source>RTCrPkixPubKeySignDigest failed: %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2653"/> + <source>Failed to create digest %s: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2717"/> + <location filename="../VBoxManageAppliance.cpp" line="2724"/> + <source>Password is given more than once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2742"/> + <source>Unknown digest type: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2755"/> + <source>Too many intermediate certificates: max %zu</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2791"/> + <source>No OVA file was specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2793"/> + <source>No signing certificate (--certificate=<file>) was specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2795"/> + <source>No signing private key (--private-key=<file>) was specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2799"/> + <source>The specified OVA file was not found: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2801"/> + <source>The specified certificate file was not found: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2803"/> + <source>The specified private key file was not found: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2824"/> + <source>Error reading certificate from '%s': %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2833"/> + <source>Successfully read the certificate and private key.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2859"/> + <source>Successfully signed '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageAppliance.cpp" line="2865"/> + <source>Error reading the private key from %s: %Rrc%#RTeim</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>BWControl</name> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="65"/> + <location filename="../VBoxManageBandwidthControl.cpp" line="88"/> + <source>Limit is too big +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="75"/> + <source>Invalid unit suffix. Valid suffixes are: k, m, g, K, M, G +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="79"/> + <source>Trailing spaces in limit! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="81"/> + <source>No digits in limit specifier +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="83"/> + <source>Invalid limit specifier +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="86"/> + <source>Limit cannot be negative +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="114"/> + <source>Bandwidth group name must not be empty! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="174"/> + <source>Invalid bandwidth group type +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="318"/> + <source>Too few parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="320"/> + <source>Too many parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="341"/> + <source>Bandwidth groups cannot be created while the VM is running +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="350"/> + <source>Bandwidth groups cannot be deleted while the VM is running +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageBandwidthControl.cpp" line="361"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Cloud</name> + <message> + <location filename="../VBoxManageCloud.cpp" line="74"/> + <source>Parameter --provider is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="79"/> + <source>Parameter --profile is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="164"/> + <source>Unknown cloud instance state "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="210"/> + <location filename="../VBoxManageCloud.cpp" line="371"/> + <source>Parameter 'compartment' is empty or absent. +Trying to get the compartment from the passed cloud profile '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="219"/> + <location filename="../VBoxManageCloud.cpp" line="380"/> + <source>Found the compartment '%s': +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="221"/> + <location filename="../VBoxManageCloud.cpp" line="382"/> + <source>Parameter --compartment-id is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="238"/> + <source>Reply is in the form 'instance name' = 'instance id' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="247"/> + <source>Failed to list instances</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="256"/> + <source>The list of the instances for the cloud profile '%ls' +and compartment '%s': +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="324"/> + <source>Unknown cloud image state "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="399"/> + <source>Reply is in the form 'image name' = 'image id' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="407"/> + <source>Failed to list images</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="416"/> + <source>The list of the images for the cloud profile '%ls' +and compartment '%s': +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="473"/> + <location filename="../VBoxManageCloud.cpp" line="553"/> + <location filename="../VBoxManageCloud.cpp" line="747"/> + <location filename="../VBoxManageCloud.cpp" line="898"/> + <location filename="../VBoxManageCloud.cpp" line="980"/> + <location filename="../VBoxManageCloud.cpp" line="1062"/> + <location filename="../VBoxManageCloud.cpp" line="1159"/> + <location filename="../VBoxManageCloud.cpp" line="1236"/> + <location filename="../VBoxManageCloud.cpp" line="1342"/> + <location filename="../VBoxManageCloud.cpp" line="1537"/> + <location filename="../VBoxManageCloud.cpp" line="1622"/> + <location filename="../VBoxManageCloud.cpp" line="1713"/> + <location filename="../VBoxManageCloud.cpp" line="1808"/> + <source>Empty command parameter list, show help. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="663"/> + <source>Warning!!! Public SSH key doesn't present in the passed arguments... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="666"/> + <source>Parameters --image-id and --boot-volume-id are mutually exclusive. Only one of them must be presented.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="670"/> + <source>Missing parameter --image-id or --boot-volume-id. One of them must be presented.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="692"/> + <source>Checking the cloud image with id '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="700"/> + <source>Checking the cloud image failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="706"/> + <source>Creating cloud instance with name '%s' from the image '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="709"/> + <source>Creating cloud instance with name '%s' from the boot volume '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="715"/> + <source>Creating cloud instance failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="718"/> + <source>Cloud instance was created successfully +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="762"/> + <location filename="../VBoxManageCloud.cpp" line="913"/> + <location filename="../VBoxManageCloud.cpp" line="995"/> + <location filename="../VBoxManageCloud.cpp" line="1077"/> + <location filename="../VBoxManageCloud.cpp" line="1386"/> + <location filename="../VBoxManageCloud.cpp" line="1728"/> + <source>Duplicate parameter: --id</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="766"/> + <location filename="../VBoxManageCloud.cpp" line="917"/> + <location filename="../VBoxManageCloud.cpp" line="999"/> + <location filename="../VBoxManageCloud.cpp" line="1081"/> + <location filename="../VBoxManageCloud.cpp" line="1390"/> + <location filename="../VBoxManageCloud.cpp" line="1732"/> + <source>Empty parameter: --id</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="787"/> + <location filename="../VBoxManageCloud.cpp" line="938"/> + <location filename="../VBoxManageCloud.cpp" line="1020"/> + <location filename="../VBoxManageCloud.cpp" line="1102"/> + <location filename="../VBoxManageCloud.cpp" line="1439"/> + <location filename="../VBoxManageCloud.cpp" line="1754"/> + <source>Missing parameter: --id</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="795"/> + <source>Getting information about cloud instance with id %s... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="796"/> + <source>Reply is in the form 'setting name' = 'value' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="817"/> + <source>Getting information about cloud instance failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="819"/> + <source>Cloud instance info (provider '%s'): +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="830"/> + <source>Availability domain = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="830"/> + <source>Availability domain wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="831"/> + <source>Instance displayed name = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="831"/> + <source>Instance displayed name wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="832"/> + <source>Instance state = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="832"/> + <source>Instance state wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="833"/> + <source>Instance Id = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="833"/> + <source>Instance Id wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="834"/> + <source>Instance name = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="834"/> + <source>Instance name wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="835"/> + <source>Bootable image Id = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="836"/> + <source>Image Id whom the instance is booted up wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="837"/> + <source>Shape of the instance = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="838"/> + <source>The shape of the instance wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="839"/> + <source>Type of guest OS = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="839"/> + <source>Type of guest OS wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="840"/> + <source>RAM = %ls MB +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="840"/> + <source>Value for RAM wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="841"/> + <source>CPUs = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="841"/> + <source>Numbers of CPUs weren't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="842"/> + <source>Instance public IP = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="842"/> + <source>Public IP wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="843"/> + <source>Free-form tags or metadata weren't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="844"/> + <source>Cloud-init script wasn't found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="946"/> + <source>Starting cloud instance with id %s... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="953"/> + <source>Starting the cloud instance failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="956"/> + <source>Cloud instance with id %s (provider = '%s', profile = '%s') was started +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1028"/> + <source>Pausing cloud instance with id %s... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1035"/> + <source>Pause the cloud instance failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1038"/> + <source>Cloud instance with id %s (provider = '%s', profile = '%s') was paused +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1111"/> + <source>Terminating cloud instance with id %s... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1118"/> + <source>Termination the cloud instance failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1121"/> + <source>Cloud instance with id %s (provider = '%s', profile = '%s') was terminated +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1293"/> + <source>Conflicting parameters: --instance-id and --object-name can't be used together. Choose one.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1302"/> + <source>Creating cloud image with name '%s' from the instance '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1305"/> + <source>Creating cloud image with name '%s' from the object '%s' in the bucket '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1313"/> + <source>Creating cloud image failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1316"/> + <source>Cloud image was created successfully +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1362"/> + <source>Duplicate parameter: --bucket-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1366"/> + <source>Empty parameter: --bucket-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1374"/> + <source>Duplicate parameter: --object-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1378"/> + <source>Empty parameter: --object-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1398"/> + <source>Duplicate parameter: --display-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1402"/> + <source>Empty parameter: --display-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1410"/> + <source>Duplicate parameter: --launch-mode</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1414"/> + <source>Empty parameter: --launch-mode</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1444"/> + <source>Missing parameter: --bucket-name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1464"/> + <source>Exporting image '%s' to the Cloud with name '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1467"/> + <source>Exporting image '%s' to the Cloud with default name +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1495"/> + <source>Image %s was found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1502"/> + <source>Process of exporting the image to the Cloud was interrupted. The image wasn't found. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1511"/> + <source>Export the image to the Cloud failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1514"/> + <source>Export the image to the Cloud was successfull +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1587"/> + <source>Creating an object '%s' from the cloud image '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1594"/> + <source>Cloud image import failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1598"/> + <source>Cloud image was imported successfully. Find the downloaded object with the name %s in the system temp folder (find the possible environment variables like TEMP, TMP and etc.) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1658"/> + <source>Getting information about the cloud image with id '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1664"/> + <source>Reply is in the form 'image property' = 'value' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1672"/> + <source>Getting information about the cloud image failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1678"/> + <source>General information about the image: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1763"/> + <source>Deleting cloud image with id %s... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1770"/> + <source>Deleting cloud image failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1773"/> + <source>Cloud image was deleted successfully +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1956"/> + <location filename="../VBoxManageCloud.cpp" line="2007"/> + <location filename="../VBoxManageCloud.cpp" line="2081"/> + <location filename="../VBoxManageCloud.cpp" line="2128"/> + <source>Missing --name parameter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1958"/> + <source>Missing --network-id parameter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="1970"/> + <source>Cloud network was created successfully +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2015"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2018"/> + <source>State: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2018"/> + <source>Enabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2018"/> + <source>Disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2021"/> + <source>CloudProvider: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2024"/> + <source>CloudProfile: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2027"/> + <source>CloudNetworkId: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2029"/> + <source>VBoxNetworkName: %ls + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2091"/> + <source>Cloud network %ls was updated successfully +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2141"/> + <source>Cloud network %ls was deleted successfully +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2209"/> + <source>Setting up tunnel network in the cloud... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2235"/> + <source>Setting up cloud network environment failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloud.cpp" line="2239"/> + <source>Cloud network environment was set up successfully. Tunnel network id is: %ls +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>CloudMachine</name> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="172"/> + <source>cloud: no providers available</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="178"/> + <source>cloud: multiple providers available, '--provider' option is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="231"/> + <source>cloud: no profiles exist</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="237"/> + <source>cloud: multiple profiles exist, '--profile' option is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="363"/> + <source>ambiguous name: %ls and %ls</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="419"/> + <source>only one machine can be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="467"/> + <source>not a valid uuid: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="530"/> + <source>machine not specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="536"/> + <source>machine name is empty</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="547"/> + <source>unable to find machine with id %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="557"/> + <source>unable to find machine with name %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="567"/> + <source>unable to find machine %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="639"/> + <source>cloud machine: RTGetOptInit: %Rra</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="654"/> + <location filename="../VBoxManageCloudMachine.cpp" line="789"/> + <source>Invalid sub-command: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="700"/> + <source>cloud machine: internal error: %d</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="705"/> + <source>cloud machine: command required +Try '--help' for more information.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="757"/> + <source>cloud machine list: unexpected machine argument</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="765"/> + <source>cloud machine list: RTGetOptInit: %Rra</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="987"/> + <source>machine is not accessible</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1017"/> + <source>State: Invalid (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1021"/> + <source>State: Provisioning (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1025"/> + <source>State: Running (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1029"/> + <source>State: Starting (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1033"/> + <source>State: Stopping (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1037"/> + <source>State: Stopped (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1041"/> + <source>State: CreatingImage (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1045"/> + <source>State: Terminating (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1049"/> + <source>State: Terminated (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1053"/> + <source>State: Unknown state (%RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1062"/> + <source>null details</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1109"/> + <source>%ls: unable to convert to boolean value +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1135"/> + <source>%ls: unable to convert to string value +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1177"/> + <source>%ls: unable to convert to integer value +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1203"/> + <source>%ls: unable to convert to choice value +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1213"/> + <source>%ls: values: %Rhra</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1223"/> + <source>%ls: selectedIndex: %Rhra</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1231"/> + <source>%ls: selected index %RI64 out of range [0, %zu) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageCloudMachine.cpp" line="1243"/> + <source>unknown value type %RU32 +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>ControlVM</name> + <message> + <location filename="../VBoxManageControlVM.cpp" line="65"/> + <source>Invalid %s number '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="222"/> + <source>Failed to send a scancode.</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageControlVM.cpp" line="323"/> + <source>Out of memory allocating %d bytes.</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="326"/> + <source>File size %RI64 is greater than %RI64: '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="329"/> + <source>Cannot get size of file '%s': %Rrc.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="334"/> + <source>Cannot open file '%s': %Rrc.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="351"/> + <location filename="../VBoxManageControlVM.cpp" line="1372"/> + <source>Not enough parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="371"/> + <source>Machine '%s' is not currently running.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="397"/> + <location filename="../VBoxManageControlVM.cpp" line="411"/> + <location filename="../VBoxManageControlVM.cpp" line="425"/> + <location filename="../VBoxManageControlVM.cpp" line="487"/> + <location filename="../VBoxManageControlVM.cpp" line="558"/> + <location filename="../VBoxManageControlVM.cpp" line="782"/> + <location filename="../VBoxManageControlVM.cpp" line="802"/> + <location filename="../VBoxManageControlVM.cpp" line="840"/> + <location filename="../VBoxManageControlVM.cpp" line="884"/> + <location filename="../VBoxManageControlVM.cpp" line="925"/> + <location filename="../VBoxManageControlVM.cpp" line="1019"/> + <location filename="../VBoxManageControlVM.cpp" line="1081"/> + <location filename="../VBoxManageControlVM.cpp" line="1131"/> + <location filename="../VBoxManageControlVM.cpp" line="1160"/> + <location filename="../VBoxManageControlVM.cpp" line="1172"/> + <location filename="../VBoxManageControlVM.cpp" line="1184"/> + <location filename="../VBoxManageControlVM.cpp" line="1197"/> + <location filename="../VBoxManageControlVM.cpp" line="1208"/> + <location filename="../VBoxManageControlVM.cpp" line="1237"/> + <location filename="../VBoxManageControlVM.cpp" line="1266"/> + <location filename="../VBoxManageControlVM.cpp" line="1297"/> + <location filename="../VBoxManageControlVM.cpp" line="1318"/> + <location filename="../VBoxManageControlVM.cpp" line="1992"/> + <location filename="../VBoxManageControlVM.cpp" line="2115"/> + <source>Missing argument to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="444"/> + <location filename="../VBoxManageControlVM.cpp" line="468"/> + <location filename="../VBoxManageControlVM.cpp" line="2226"/> + <source>Invalid value '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="453"/> + <location filename="../VBoxManageControlVM.cpp" line="477"/> + <source>Audio adapter not enabled in VM configuration.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="498"/> + <location filename="../VBoxManageControlVM.cpp" line="528"/> + <source>Missing argument to '%s %s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="513"/> + <location filename="../VBoxManageControlVM.cpp" line="536"/> + <source>Invalid '%s %s' argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="547"/> + <location filename="../VBoxManageControlVM.cpp" line="574"/> + <source>Invalid '%s' argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="591"/> + <source>Failed to power off machine.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="611"/> + <source>Machine in invalid state %d -- %s.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="634"/> + <source>Failed to save machine state.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="665"/> + <location filename="../VBoxManageControlVM.cpp" line="700"/> + <location filename="../VBoxManageControlVM.cpp" line="754"/> + <location filename="../VBoxManageControlVM.cpp" line="775"/> + <location filename="../VBoxManageControlVM.cpp" line="1478"/> + <location filename="../VBoxManageControlVM.cpp" line="1500"/> + <location filename="../VBoxManageControlVM.cpp" line="1624"/> + <location filename="../VBoxManageControlVM.cpp" line="1658"/> + <location filename="../VBoxManageControlVM.cpp" line="1755"/> + <location filename="../VBoxManageControlVM.cpp" line="2001"/> + <source>Guest not running.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="686"/> + <source>Current installed Guest Additions don't support rebooting the guest.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="688"/> + <source>Current installed Guest Additions don't support shutting down the guest.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="707"/> + <source>Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="727"/> + <source>Converting '%s' returned %Rrc!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="736"/> + <source>'%s' is not a hex byte!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="761"/> + <source>Missing argument to '%s'. Expected ASCII string(s).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="814"/> + <source>Invalid link state '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="860"/> + <source>Filename not specified for NIC %lu.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="868"/> + <source>The NIC %d is currently disabled and thus its tracefile can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="901"/> + <source>Invalid nictrace%lu argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="909"/> + <source>The NIC %d is currently disabled and thus its trace flag can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="961"/> + <source>Missing or invalid argument to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="996"/> + <source>Wrong rule proto '%s' specified -- only 'udp' and 'tcp' are allowed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1050"/> + <source>Invalid nicproperty%d argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1057"/> + <source>Failed to allocate memory for nicproperty%d '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1065"/> + <source>The NIC %d is currently disabled and thus its properties can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1105"/> + <source>Unknown promiscuous mode policy '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1115"/> + <source>The NIC %d is currently disabled and thus its promiscuous mode can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1217"/> + <source>Invalid type '%s' specfied for NIC %lu.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1225"/> + <source>The NIC %d is currently disabled and thus its attachment type can't be changed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1233"/> + <source>'vrdp' is deprecated. Use 'vrde'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1249"/> + <source>Invalid remote desktop server state '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1262"/> + <source>'vrdpport' is deprecated. Use 'vrdeport'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1293"/> + <source>'vrdpvideochannelquality' is deprecated. Use 'vrdevideochannelquality'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1344"/> + <source>Invalid vrdeproperty argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1351"/> + <source>Failed to allocate memory for VRDE property '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1378"/> + <source>Wrong number of arguments.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1392"/> + <location filename="../VBoxManageControlVM.cpp" line="1587"/> + <location filename="../VBoxManageControlVM.cpp" line="2259"/> + <source>Invalid parameter '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1425"/> + <source>Zero UUID argument '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1444"/> + <location filename="../VBoxManageControlVM.cpp" line="1491"/> + <location filename="../VBoxManageControlVM.cpp" line="1542"/> + <location filename="../VBoxManageControlVM.cpp" line="1599"/> + <location filename="../VBoxManageControlVM.cpp" line="1638"/> + <location filename="../VBoxManageControlVM.cpp" line="1735"/> + <location filename="../VBoxManageControlVM.cpp" line="1787"/> + <location filename="../VBoxManageControlVM.cpp" line="1821"/> + <location filename="../VBoxManageControlVM.cpp" line="1840"/> + <location filename="../VBoxManageControlVM.cpp" line="1854"/> + <location filename="../VBoxManageControlVM.cpp" line="1888"/> + <location filename="../VBoxManageControlVM.cpp" line="1910"/> + <location filename="../VBoxManageControlVM.cpp" line="1932"/> + <location filename="../VBoxManageControlVM.cpp" line="1954"/> + <location filename="../VBoxManageControlVM.cpp" line="1978"/> + <location filename="../VBoxManageControlVM.cpp" line="2048"/> + <location filename="../VBoxManageControlVM.cpp" line="2093"/> + <source>Incorrect number of parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1462"/> + <source>Either "yes" or "no" is expected.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1527"/> + <source>Display status must be <on> or <off>.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1647"/> + <source>Error parsing guest memory balloon size '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1728"/> + <source>Teleportation failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1746"/> + <source>Error parsing display number '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1769"/> + <source>Failed to create file '%s' (%Rrc).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1776"/> + <source>Failed to write screenshot to file '%s' (%Rrc).</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1827"/> + <source>Error parsing list of screen IDs '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1863"/> + <source>Error parsing video width '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1872"/> + <source>Error parsing video height '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1897"/> + <source>Error parsing video rate '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1919"/> + <source>Error parsing video FPS '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1941"/> + <source>Error parsing maximum time '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="1963"/> + <source>Error parsing maximum file size '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2037"/> + <source>Invalid argument to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2059"/> + <source>Invalid parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2072"/> + <source>Enter password:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2081"/> + <source>Failed to read new password from file.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2129"/> + <location filename="../VBoxManageControlVM.cpp" line="2144"/> + <location filename="../VBoxManageControlVM.cpp" line="2185"/> + <location filename="../VBoxManageControlVM.cpp" line="2198"/> + <location filename="../VBoxManageControlVM.cpp" line="2219"/> + <location filename="../VBoxManageControlVM.cpp" line="2239"/> + <source>Incorrect arguments to '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2205"/> + <source>Invalid vm-process-priority '%s'.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageControlVM.cpp" line="2248"/> + <source>Invalid autostart delay number '%s'.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>DHCPServer</name> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="65"/> + <source>Either --network or --interface, not both</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="70"/> + <source>Either --interface or --network, not both</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="180"/> + <source>Failed to locate host-only interface '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="194"/> + <source>Failed to find DHCP server for network '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="196"/> + <source>Failed to find DHCP server for host-only interface '%s' (network '%ls')</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="200"/> + <location filename="../VBoxManageDHCPServer.cpp" line="890"/> + <source>You need to specify either --network or --interface to identify the DHCP server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="474"/> + <source>Incomplete option sequence preseeding '--global'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="480"/> + <source>Incomplete option sequence preseeding '--group'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="482"/> + <source>Group name cannot be empty</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="488"/> + <source>Incomplete option sequence preseeding '--mac-address'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="495"/> + <source>Incomplete option sequence preseeding '--vm'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="501"/> + <source>--nic option requires a --vm preceeding selecting the VM it should apply to</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="503"/> + <source>Incomplete option sequence preseeding '--nic=%u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="505"/> + <source>invalid NIC number: %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="540"/> + <source>Malformed hex string given to --set-opt-hex %u: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="555"/> + <source>--del-opt does not apply to the 'add' subcommand</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="567"/> + <source>--unforce-opt does not apply to the 'add' subcommand</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="571"/> + <source>--unsuppress-opt does not apply to the 'add' subcommand</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="629"/> + <source>--zap-options does not apply to the 'add' subcommand</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="671"/> + <source>--remove-config does not apply to the 'add' subcommand</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="673"/> + <source>--remove-config cannot be applied to the global config</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="686"/> + <source>--fixed-address can only be applied to a VM NIC or an MAC address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="720"/> + <source>A group must be selected to perform condition alterations.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="722"/> + <source>Condition value cannot be empty</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="815"/> + <source>Could not find any condition of type %d with value '%s' to delete</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="823"/> + <source>--zap-conditions can only be with a group selected</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="842"/> + <source>Incomplete option sequence preseeding '--id=%u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="849"/> + <source>--value without --id=dhcp-opt-no</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="863"/> + <source>--remove does not apply to the 'add' subcommand</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="865"/> + <source>--remove without --id=dhcp-opt-no</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="895"/> + <source>Missing required option: --ip</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="897"/> + <source>Missing required option: --netmask</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="899"/> + <source>Missing required option: --lowerip</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="901"/> + <source>Missing required option: --upperip</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="919"/> + <source>Could not find interface '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="923"/> + <source>Could not get network name for the interface '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="934"/> + <source>DHCP server already exists</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="938"/> + <source>Failed to create the DHCP server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="941"/> + <source>DHCP server does not exist</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="973"/> + <source>Failed to set configuration (%ls, %ls, %ls, %ls)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1025"/> + <source>Failed to remove server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1092"/> + <source>Failed to start the server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1136"/> + <source>Failed to restart the server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1180"/> + <source>Failed to stop the server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1227"/> + <source>You need to specify a MAC address too look for</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDHCPServer.cpp" line="1255"/> + <source>IP Address: %ls +MAC Address: %RTmac +State: %ls +Issued: %s (%RU64) +Expire: %s (%RU64) +TTL: %RU64 sec, currently %RU64 sec left +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>DebugVM</name> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="115"/> + <source>The getregisters sub-command takes at least one register name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="156"/> + <source>Must specify info item to display</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="303"/> + <source>The --compression option has already been given</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="308"/> + <source>The --filename option has already been given</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="317"/> + <source>The --filename option is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="325"/> + <source>RTPathAbs failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="351"/> + <source>Detected: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="371"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="372"/> + <source>Version: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="450"/> + <source>setregisters expects input on the form 'register=value' got '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="462"/> + <source>Out of memory +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="474"/> + <source>The setregisters sub-command takes at least one register name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="483"/> + <source>Successfully set %ls +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDebugVM.cpp" line="489"/> + <source>Successfully set %u registers +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="516"/> + <source>export %s='%ls' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="518"/> + <source>set %s=%ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="533"/> + <source>Debug logger settings: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="557"/> + <source>Release logger settings: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="631"/> + <source>The show sub-command has no idea what '%s' might be</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="705"/> + <source>====================== CPU #%u ====================== +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="752"/> + <source>Multiple --pattern options are not permitted</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="766"/> + <source>The --reset and --descriptions options does not mix</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="836"/> + <source>The --filename is missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDebugVM.cpp" line="960"/> + <source>Machine '%s' is not currently running. +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Disk</name> + <message> + <location filename="../VBoxManageDisk.cpp" line="64"/> + <source>Error code %Rrc at %s(%u) in function %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="184"/> + <location filename="../VBoxManageDisk.cpp" line="219"/> + <source>Cannot convert filename "%s" to absolute path</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="288"/> + <source>Out of memory copying '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="328"/> + <location filename="../VBoxManageDisk.cpp" line="334"/> + <location filename="../VBoxManageDisk.cpp" line="340"/> + <location filename="../VBoxManageDisk.cpp" line="699"/> + <location filename="../VBoxManageDisk.cpp" line="705"/> + <location filename="../VBoxManageDisk.cpp" line="711"/> + <location filename="../VBoxManageDisk.cpp" line="1025"/> + <location filename="../VBoxManageDisk.cpp" line="1031"/> + <location filename="../VBoxManageDisk.cpp" line="1037"/> + <location filename="../VBoxManageDisk.cpp" line="1660"/> + <location filename="../VBoxManageDisk.cpp" line="1666"/> + <location filename="../VBoxManageDisk.cpp" line="1672"/> + <location filename="../VBoxManageDisk.cpp" line="1772"/> + <location filename="../VBoxManageDisk.cpp" line="1778"/> + <location filename="../VBoxManageDisk.cpp" line="1784"/> + <source>Only one command can be specified: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="371"/> + <source>Invalid key value pair: No '='.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="387"/> + <source>Cannot open replacement value file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="403"/> + <source>Error reading replacement MBR file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="406"/> + <source>Out of memory reading '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="410"/> + <source>Replacement value file '%s' is to big: %Rhcb, max 16MiB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="414"/> + <source>Cannot get the size of the value file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="433"/> + <location filename="../VBoxManageDisk.cpp" line="1060"/> + <location filename="../VBoxManageDisk.cpp" line="1245"/> + <location filename="../VBoxManageDisk.cpp" line="2585"/> + <source>Invalid medium variant '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="437"/> + <location filename="../VBoxManageDisk.cpp" line="799"/> + <location filename="../VBoxManageDisk.cpp" line="1069"/> + <location filename="../VBoxManageDisk.cpp" line="1261"/> + <location filename="../VBoxManageDisk.cpp" line="1680"/> + <location filename="../VBoxManageDisk.cpp" line="1796"/> + <location filename="../VBoxManageDisk.cpp" line="2008"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="443"/> + <location filename="../VBoxManageDisk.cpp" line="806"/> + <location filename="../VBoxManageDisk.cpp" line="1687"/> + <location filename="../VBoxManageDisk.cpp" line="1803"/> + <location filename="../VBoxManageDisk.cpp" line="2015"/> + <source>Invalid option -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="445"/> + <location filename="../VBoxManageDisk.cpp" line="808"/> + <location filename="../VBoxManageDisk.cpp" line="1689"/> + <location filename="../VBoxManageDisk.cpp" line="1805"/> + <location filename="../VBoxManageDisk.cpp" line="2017"/> + <source>Invalid option case %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="448"/> + <location filename="../VBoxManageDisk.cpp" line="811"/> + <location filename="../VBoxManageDisk.cpp" line="1692"/> + <location filename="../VBoxManageDisk.cpp" line="1808"/> + <location filename="../VBoxManageDisk.cpp" line="2020"/> + <source>unknown option: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="452"/> + <location filename="../VBoxManageDisk.cpp" line="815"/> + <location filename="../VBoxManageDisk.cpp" line="1085"/> + <location filename="../VBoxManageDisk.cpp" line="1696"/> + <location filename="../VBoxManageDisk.cpp" line="1812"/> + <location filename="../VBoxManageDisk.cpp" line="2024"/> + <source>error: %Rrs</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="463"/> + <location filename="../VBoxManageDisk.cpp" line="483"/> + <source>Parameters --filename is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="465"/> + <source>Parameters --size is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="486"/> + <source>Creating a differencing medium is only supported for hard disks</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="505"/> + <source>Invalid parent hard disk reference, avoiding crash</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="588"/> + <source>The %s is not found in the property list of the requested medium format.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="598"/> + <source>Base64 encoding of the property %s failed. (%Rhrc)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="622"/> + <source>Failed to create medium</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="630"/> + <source>Medium created. UUID: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="718"/> + <source>Invalid medium type '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="725"/> + <source>Invalid autoreset parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="748"/> + <source>Invalid --property argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="755"/> + <source>Error: Failed to allocate memory for medium property '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="823"/> + <location filename="../VBoxManageDisk.cpp" line="1705"/> + <location filename="../VBoxManageDisk.cpp" line="1820"/> + <source>Medium name or UUID required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="834"/> + <source>No operation specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="855"/> + <source>Invalid medium reference, avoiding crash</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="876"/> + <source>Error: Attempt to resize the medium from %RU64.%RU64 MB to %RU64.%RU64 MB. Use --resizebyte if this is intended! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="910"/> + <source>Compact medium operation is not implemented!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="912"/> + <source>Compact medium operation for this format is not implemented yet!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="914"/> + <source>Failed to compact medium</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="916"/> + <source>Failed to compact medium!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="929"/> + <source>Failed to resize medium</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="931"/> + <source>Resize medium operation is not implemented!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="933"/> + <source>Resize medium operation for this format is not implemented yet!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="935"/> + <source>Failed to resize medium!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="951"/> + <source>Failed to move medium</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="957"/> + <source>Move medium with UUID %s finished +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="970"/> + <source>Set new location of medium with UUID %s finished +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="977"/> + <source>Medium description has been changed. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1076"/> + <source>unhandled option: -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1078"/> + <source>unhandled option: %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1081"/> + <source>unknown option: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1092"/> + <source>Mandatory UUID or input file parameter missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1094"/> + <source>Mandatory output file parameter missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1096"/> + <source>Specified options which cannot be used with --existing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1184"/> + <source>Failed to clone medium</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1189"/> + <source>Clone medium created in format '%ls'. UUID: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1233"/> + <source>Invalid UUID '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1270"/> + <source>Incorrect number of parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1271"/> + <source>Converting from raw image file="%s" to file="%s"... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1293"/> + <source>Cannot open file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1305"/> + <source>Cannot get image size for file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDisk.cpp" line="1309"/> + <source>Creating %s image with size %RU64 bytes (%RU64MB)... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1310"/> + <source>fixed</source> + <comment>adjective</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1310"/> + <source>dynamic</source> + <comment>adjective</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1313"/> + <source>Converted image from %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1317"/> + <source>Cannot create the virtual disk container: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1335"/> + <source>Cannot create the disk image "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1345"/> + <source>Out of memory allocating buffers for image "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1364"/> + <source>Failed to write to disk image "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1393"/> + <source>Parent UUID: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1398"/> + <location filename="../VBoxManageDisk.cpp" line="1445"/> + <location filename="../VBoxManageDisk.cpp" line="1500"/> + <source>unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1402"/> + <source>not created</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1405"/> + <source>created</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1408"/> + <source>locked read</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1411"/> + <source>locked write</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1414"/> + <source>inaccessible</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1417"/> + <source>creating</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1420"/> + <source>deleting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1426"/> + <source>State: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1432"/> + <source>Access Error: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1440"/> + <source>Description: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1450"/> + <source>normal (differencing)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1452"/> + <source>normal (base)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1455"/> + <source>immutable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1458"/> + <source>writethrough</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1461"/> + <source>shareable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1464"/> + <source>readonly</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1467"/> + <source>multiattach</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1473"/> + <source>Type: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1480"/> + <source>Auto-Reset: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1480"/> + <source>on</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1480"/> + <source>off</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1485"/> + <source>Location: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1489"/> + <source>Storage format: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1504"/> + <source>split2G</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1507"/> + <source>streamOptimized</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1510"/> + <source>ESX</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1513"/> + <source>default</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1516"/> + <source>dynamic</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1518"/> + <source>fixed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1520"/> + <source>differencing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1521"/> + <source>Format variant: %s %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1526"/> + <source>Capacity: %lld MBytes +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1531"/> + <source>Size on disk: %lld MBytes +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1539"/> + <source>Encryption: enabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1542"/> + <source>Cipher: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1543"/> + <source>Password ID: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1547"/> + <source>Encryption: disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1563"/> + <source>Property: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1584"/> + <source>In use by VMs: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1619"/> + <source>Child UUIDs: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1725"/> + <source>base</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1845"/> + <source>Failed to delete medium</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1848"/> + <source>Failed to delete medium. Error code %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1884"/> + <source>unexpected parameter %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1897"/> + <source>Missing action</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1903"/> + <source>Invalid action given: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="1909"/> + <source>Invalid number of arguments given for action: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2029"/> + <source>Disk name or UUID required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2032"/> + <source>No password specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2036"/> + <source>A new password must always have a valid identifier set at the same time</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2043"/> + <source>Enter new password:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2052"/> + <source>Failed to read new password from file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2063"/> + <source>Enter old password:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2072"/> + <source>Failed to read old password from file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2085"/> + <location filename="../VBoxManageDisk.cpp" line="2144"/> + <source>Invalid hard disk reference, avoiding crash</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2096"/> + <source>Encrypt hard disk operation is not implemented!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2098"/> + <source>Encrypt hard disk operation for this cipher is not implemented yet!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2100"/> + <source>Failed to encrypt hard disk</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2102"/> + <source>Failed to encrypt hard disk!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2116"/> + <source>Invalid number of arguments: %d</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2123"/> + <source>Enter password:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2132"/> + <source>Failed to read password from file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2148"/> + <source>The given password is correct +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2226"/> + <source>No medium specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2237"/> + <source>Enter encryption password:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2389"/> + <location filename="../VBoxManageDisk.cpp" line="2610"/> + <source>Error opening '%s' for writing: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2405"/> + <source>Specified offset (%#RX64) is beyond the end of the medium (%#RX64)</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDisk.cpp" line="2435"/> + <source>Read(%zu bytes at %#RX64)</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2464"/> + <source>********** <ditto x %RU64> +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2513"/> + <location filename="../VBoxManageDisk.cpp" line="2654"/> + <source>Error writing to '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageDisk.cpp" line="2521"/> + <source>Expected read() at offset %RU64 (%#RX64) to return %#zx bytes, only got %#zx! +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageDisk.cpp" line="2537"/> + <location filename="../VBoxManageDisk.cpp" line="2675"/> + <source>Error closing '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>GuestCtrl</name> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="276"/> + <source>Unable to install console control handler, rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="303"/> + <source>Unable to uninstall console control handler, rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="332"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="398"/> + <source>starting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="334"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="367"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="400"/> + <source>started</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="336"/> + <source>paused</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="338"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="402"/> + <source>terminating</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="340"/> + <source>successfully terminated</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="342"/> + <source>terminated by signal</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="344"/> + <source>abnormally aborted</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="346"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="375"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="406"/> + <source>timed out</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="348"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="408"/> + <source>timed out, hanging</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="350"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="410"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="435"/> + <source>killed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="352"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="373"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="412"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="437"/> + <source>error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="356"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="387"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="416"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="441"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="451"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="464"/> + <source>unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="369"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="404"/> + <source>terminated</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="371"/> + <source>status changed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="377"/> + <source>stdin ready</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="379"/> + <source>data on stdout</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="381"/> + <source>data on stderr</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="383"/> + <source>waiting flag not supported</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="427"/> + <source>opening</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="429"/> + <source>open</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="431"/> + <source>closing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="433"/> + <source>closed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="452"/> + <source>fifo</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="453"/> + <source>char-device</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="454"/> + <source>directory</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="455"/> + <source>block-device</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="456"/> + <source>file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="457"/> + <source>symlink</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="458"/> + <source>socket</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="459"/> + <source>white-out</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="478"/> + <source>Error details:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="483"/> + <source>Object has indicated no error (%Rhrc)!? +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="515"/> + <source>Could not lookup progress information +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="574"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3247"/> + <source>Out of memory</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="602"/> + <source>The --username|-u option is ignored by '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="609"/> + <source>Password is given more than once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="613"/> + <source>The --password option is ignored by '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="620"/> + <source>The --password-file|-p option is ignored by '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="627"/> + <source>The --domain option is ignored by '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="692"/> + <source>Failed to get a IConsole pointer for the machine. Is it still running? +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="697"/> + <source>Machine "%s" is not running (currently %s)! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="726"/> + <source>[%RU32] VBoxManage Guest Control [%s] - %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="728"/> + <source>No enough memory for session name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="734"/> + <source>Creating guest session as user '%s'... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="745"/> + <source>Out of memory setting up IGuest::CreateSession call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="754"/> + <source>Waiting for guest session to start... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="766"/> + <source>Out of memory setting up IGuestSession::WaitForArray call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="782"/> + <source>Successfully started guest session (ID %RU32) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="791"/> + <source>Error starting guest session (current status is: %s) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="792"/> + <source><unknown></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="851"/> + <source>No user name specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="891"/> + <source>Closing guest session ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="897"/> + <source>Guest session detached +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1058"/> + <source>Unable to write output, rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1088"/> + <source>Unsupported %s line ending conversion</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1093"/> + <source>Error getting %s handle: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1216"/> + <source>Invalid argument variable[=value]: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1226"/> + <source>Warning: Deprecated option "--no-profile" specified +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1292"/> + <source>No executable specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1344"/> + <source>Starting guest process ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1346"/> + <source>Starting guest process (within %ums) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1368"/> + <source>Process '%s' (PID %RU32) started +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1373"/> + <source>[%RU32 - Session %RU32] +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1394"/> + <source>waitResult: %d +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1410"/> + <source>Process terminated +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1487"/> + <source>Process execution aborted! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1493"/> + <source>Process successfully started! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1507"/> + <source>Exit code=%u (Status=%u [%s]) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1516"/> + <source>Process timed out (guest side) and %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1518"/> + <source>failed to terminate so far</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1518"/> + <source>was terminated</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1524"/> + <source>Process now is in status [%s] (unexpected) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1532"/> + <source>Process monitor loop quit with vrc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1538"/> + <source>Process monitor loop timed out +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1641"/> + <source>No sources specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1649"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="2201"/> + <source>No destination specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1658"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1762"/> + <source>RTPathAbs failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1671"/> + <source>Copying from host to guest ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1673"/> + <source>Copying from guest to host ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1685"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1759"/> + <source>RTPathQueryInfo failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1703"/> + <source>Destination must be a directory!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1735"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1796"/> + <source>File '%s' -> '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1744"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1782"/> + <source>Directory '%s' -> '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1756"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="1805"/> + <source>Not a file or directory: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1811"/> + <source>FsObjQueryInfo failed on '%s': %Rhrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1825"/> + <source>File copy failed</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="1894"/> + <source>Creating %RU32 directories... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1898"/> + <source>mkdir was interrupted by Ctrl-C (%u left) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1911"/> + <source>Creating directory "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1922"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="2006"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="2127"/> + <source>Out of memory +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1932"/> + <source>No directory to create specified!</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="1980"/> + <source>Removing %RU32 directory tree(s)... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="1983"/> + <source>Removing %RU32 directorie(s)... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1988"/> + <source>rmdir was interrupted by Ctrl-C (%u left) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="1999"/> + <source>Removing directory "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2018"/> + <source>Recursively removing directory "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2036"/> + <source>Directory deletion failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2042"/> + <source>Out of memory during recursive rmdir +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2060"/> + <source>No directory to remove specified!</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="2100"/> + <source>Removing %RU32 file(s)... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2104"/> + <source>rm was interrupted by Ctrl-C (%u left) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2115"/> + <source>Removing file "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2137"/> + <source>No file to remove specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2195"/> + <source>Failed to initialize, rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2199"/> + <source>No source(s) to move specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2220"/> + <source>Destination does not exist +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2230"/> + <source>Destination must be a directory when specifying multiple sources +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2234"/> + <source>Unable to determine destination type: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2243"/> + <source>Renaming %RU32 %s ... +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="2244"/> + <source>sources</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2244"/> + <source>source</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2259"/> + <source>Cannot stat "%s": No such file or directory +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2276"/> + <source>Renaming %s "%s" to "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2277"/> + <source>directory</source> + <comment>object</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2277"/> + <source>file</source> + <comment>object</comment> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2296"/> + <source>Warning: Not all sources were renamed +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2355"/> + <source>More than one template specified! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2364"/> + <source>No template specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2367"/> + <source>Creating temporary files is currently not supported!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2379"/> + <source>Creating temporary directory from template '%s' in directory '%s' ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2382"/> + <source>Creating temporary directory from template '%s' in default temporary directory ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2385"/> + <source>Creating temporary file from template '%s' in directory '%s' ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2388"/> + <source>Creating temporary file from template '%s' in default temporary directory ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2401"/> + <source>Directory name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2444"/> + <source>Command "%s" not implemented yet!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2452"/> + <source>Nothing to stat!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2465"/> + <source>Checking for element "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2475"/> + <source>Failed to stat '%s': No such file +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2480"/> + <source> File: '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2515"/> + <source> Size: %-17RU64 Alloc: %-19RU64 Type: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2517"/> + <source>Device: %#-17RX32 INode: %-18RU64 Links: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2528"/> + <source> Mode: %-16s Attrib: %-17s Dev ID: %#RX32 +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2530"/> + <source> Mode: %-16s Attrib: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2532"/> + <source> Owner: %4d/%-12ls Group: %4d/%ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2536"/> + <source> Birth: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2538"/> + <source>Change: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2540"/> + <source>Modify: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2542"/> + <source>Access: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2595"/> + <source>Current run level is %RU32 +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2602"/> + <source>Waiting for run level %RU32 ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2615"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3565"/> + <source>Waiting failed with %Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2621"/> + <source>Run level %RU32 reached +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2630"/> + <source>Run level %RU32 not reached within time +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2716"/> + <source>RTPathAbsCxx failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2745"/> + <source>Updating Guest Additions ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2761"/> + <source>No Guest Additions source found or specified, aborting +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2766"/> + <source>Source "%s" does not exist! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2777"/> + <source>OS type:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2782"/> + <source>Additions run level:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2794"/> + <source>Additions version:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2802"/> + <source>Using source: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2811"/> + <source>Waiting for current Guest Additions inside VM getting ready for updating ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2832"/> + <source>Guest Additions %lsr%RU64 currently installed, waiting for Guest Additions installer to start ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2856"/> + <source>Guest Additions update failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2861"/> + <source>Guest Additions update successful. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2866"/> + <source>Rebooting guest ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2874"/> + <source>Current installed Guest Additions don't support automatic rebooting. Please reboot manually. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2886"/> + <source>Waiting for new Guest Additions inside VM getting ready ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2894"/> + <source>Verifying Guest Additions update ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2913"/> + <source>Old Guest Additions: %ls%RU64 +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2915"/> + <source>New Guest Additions: %ls%RU64 +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2920"/> + <source> +Error updating Guest Additions, please check guest installer log +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2925"/> + <source> +WARNING: Guest Additions were downgraded +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="2932"/> + <source>The guest needs to be restarted in order to make use of the updated Guest Additions. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3005"/> + <source>Invalid run level specified. Valid values are: system, userland, desktop</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3019"/> + <source>Missing run level to wait for</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3066"/> + <source>Unknown list: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3076"/> + <source>Missing list name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3097"/> + <source>Active guest sessions: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3116"/> + <source> + Session #%-3zu ID=%-3RU32 User=%-16ls Status=[%s] Name=%ls</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3139"/> + <source> + Process #%-03zu PID=%-6RU32 Status=[%s] Command=%ls</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3167"/> + <source> + File #%-03zu ID=%-6RU32 Status=[%s] Name=%ls</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3178"/> + <source> + +Total guest sessions: %zu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3180"/> + <source>Total guest processes: %zu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3182"/> + <source>Total guest files: %zu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3185"/> + <source>No active guest sessions found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3251"/> + <source>Invalid PID value: 0</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3254"/> + <source>Error parsing PID value: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3264"/> + <source>At least one PID must be specified to kill!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3268"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3422"/> + <source>No session ID specified!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3272"/> + <location filename="../VBoxManageGuestCtrl.cpp" line="3426"/> + <source>Either session ID or name (pattern) must be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3335"/> + <source>Terminating process (PID %RU32) (session ID %RU32) ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3343"/> + <source>No matching process(es) for session ID %RU32 found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3355"/> + <source>No matching session(s) found +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageGuestCtrl.cpp" line="3358"/> + <source>%RU32 process(es) terminated +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3464"/> + <source>Closing guest session ID=#%RU32 "%s" ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3468"/> + <source>Guest session successfully closed +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3476"/> + <source>No guest session(s) found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3554"/> + <source>Waiting for events ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3709"/> + <source>Unknown sub-command: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3718"/> + <source>Missing sub-command</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrl.cpp" line="3720"/> + <source>Missing VM name and sub-command</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>GuestCtrlLsnr</name> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="106"/> + <source>File ID=%RU32 "%s" changed status to [%s] +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="162"/> + <source>Process PID=%RU32 "%s" changed status to [%s] +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="254"/> + <source>File "%s" %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="256"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="320"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="461"/> + <source>registered</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="256"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="320"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="461"/> + <source>unregistered</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="260"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="324"/> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="465"/> + <source>Registering ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="283"/> + <source>Unregistering file ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="318"/> + <source>Process "%s" %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="347"/> + <source>Unregistering process ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="384"/> + <source>Session ID=%RU32 "%s" changed status to [%s] +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="459"/> + <source>Session ID=%RU32 "%s" %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="490"/> + <source>Unregistering ... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestCtrlListener.cpp" line="552"/> + <source>Reached run level %RU32 +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>GuestProp</name> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="64"/> + <location filename="../VBoxManageGuestProp.cpp" line="125"/> + <location filename="../VBoxManageGuestProp.cpp" line="171"/> + <location filename="../VBoxManageGuestProp.cpp" line="215"/> + <location filename="../VBoxManageGuestProp.cpp" line="304"/> + <location filename="../VBoxManageGuestProp.cpp" line="407"/> + <location filename="../VBoxManageGuestProp.cpp" line="422"/> + <source>Incorrect parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="84"/> + <source>No value set! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="86"/> + <source>Value: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="89"/> + <source>Timestamp: %lld +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="90"/> + <source>Flags: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="251"/> + <source>No properties found. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="253"/> + <source>Name: %ls, value: %ls, timestamp: %lld, flags: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="362"/> + <source>Property %ls was deleted +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="364"/> + <source>Name: %ls, value: %ls, flags: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageGuestProp.cpp" line="381"/> + <source>Time out or interruption while waiting for a notification.</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Help</name> + <message> + <location filename="../VBoxManageHelp.cpp" line="139"/> + <source>Usage - %s%s: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="142"/> + <source>Usage: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="231"/> + <source>No subcommand specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="257"/> + <source>Unknown subcommand: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="290"/> + <source>Too many parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="397"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="401"/> + <source>Invalid option -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="403"/> + <source>Invalid option case %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="406"/> + <source>Unknown option: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="408"/> + <source>Invalid argument format: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="432"/> + <source>Missing the %u%s value for option %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="434"/> + <source>st</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="435"/> + <source>nd</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="436"/> + <source>rd</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHelp.cpp" line="437"/> + <source>th</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>HostOnly</name> + <message> + <location filename="../VBoxManageHostonly.cpp" line="95"/> + <source>Failed to create the host-only adapter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="104"/> + <source>Interface '%ls' was successfully created +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="123"/> + <location filename="../VBoxManageHostonly.cpp" line="214"/> + <source>Only one interface name can be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="131"/> + <source>No interface name was specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="149"/> + <source>Failed to remove the host-only adapter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="193"/> + <source>The --ip option is specified more than once</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="198"/> + <source>The --netmask option is specified more than once</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="203"/> + <source>The --ipv6 option is specified more than once</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="208"/> + <source>The --netmasklengthv6 option is specified more than once</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="224"/> + <source>You can not use --dhcp with static ip configuration parameters: --ip, --netmask, --ipv6 and --netmasklengthv6.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="226"/> + <source>You can not use ipv4 configuration (--ip and --netmask) with ipv6 (--ipv6 and --netmasklengthv6) simultaneously.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="234"/> + <source>Could not find interface '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="250"/> + <source>IPv6 setting is not supported for this adapter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="259"/> + <source>Neither -dhcp nor -ip nor -ipv6 was specfified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="268"/> + <location filename="../VBoxManageHostonly.cpp" line="514"/> + <source>No sub-command specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="289"/> + <location filename="../VBoxManageHostonly.cpp" line="533"/> + <source>Unknown sub-command '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="410"/> + <source>The --name parameter must be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="412"/> + <source>The --netmask parameter must be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="414"/> + <source>The --lower-ip parameter must be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="416"/> + <source>The --upper-ip parameter must be specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageHostonly.cpp" line="447"/> + <location filename="../VBoxManageHostonly.cpp" line="503"/> + <source>Either --name or --id parameter must be specified</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Info</name> + <message> + <location filename="../VBoxManageInfo.cpp" line="85"/> + <location filename="../VBoxManageInfo.cpp" line="108"/> + <location filename="../VBoxManageInfo.cpp" line="131"/> + <location filename="../VBoxManageInfo.cpp" line="2240"/> + <location filename="../VBoxManageInfo.cpp" line="2349"/> + <location filename="../VBoxManageInfo.cpp" line="2882"/> + <location filename="../VBoxManageInfo.cpp" line="2884"/> + <source>enabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="85"/> + <location filename="../VBoxManageInfo.cpp" line="108"/> + <location filename="../VBoxManageInfo.cpp" line="131"/> + <location filename="../VBoxManageInfo.cpp" line="1263"/> + <location filename="../VBoxManageInfo.cpp" line="1317"/> + <location filename="../VBoxManageInfo.cpp" line="2240"/> + <location filename="../VBoxManageInfo.cpp" line="2350"/> + <location filename="../VBoxManageInfo.cpp" line="2882"/> + <location filename="../VBoxManageInfo.cpp" line="2884"/> + <source>disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="284"/> + <source> %sName: %ls (UUID: %s)%s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="290"/> + <source> %sDescription: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="292"/> + <source> %sDescription: +%ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="341"/> + <source>powered off</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="343"/> + <source>saved</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="345"/> + <source>teleported</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="347"/> + <source>aborted</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="349"/> + <source>aborted-saved</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="351"/> + <source>running</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="353"/> + <location filename="../VBoxManageInfo.cpp" line="399"/> + <source>paused</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="355"/> + <source>guru meditation</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="357"/> + <source>teleporting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="359"/> + <source>live snapshotting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="361"/> + <source>starting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="363"/> + <source>stopping</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="365"/> + <source>saving</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="367"/> + <source>restoring</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="369"/> + <source>teleporting paused vm</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="371"/> + <source>teleporting (incoming)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="373"/> + <source>deleting snapshot live</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="375"/> + <source>deleting snapshot live paused</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="377"/> + <source>online snapshotting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="379"/> + <source>restoring snapshot</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="381"/> + <source>deleting snapshot</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="383"/> + <source>setting up</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="385"/> + <source>offline snapshotting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="389"/> + <location filename="../VBoxManageInfo.cpp" line="416"/> + <location filename="../VBoxManageInfo.cpp" line="446"/> + <location filename="../VBoxManageInfo.cpp" line="699"/> + <location filename="../VBoxManageInfo.cpp" line="1186"/> + <location filename="../VBoxManageInfo.cpp" line="1206"/> + <location filename="../VBoxManageInfo.cpp" line="1806"/> + <location filename="../VBoxManageInfo.cpp" line="1860"/> + <location filename="../VBoxManageInfo.cpp" line="2412"/> + <source>unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="397"/> + <location filename="../VBoxManageInfo.cpp" line="2738"/> + <location filename="../VBoxManageInfo.cpp" line="2828"/> + <location filename="../VBoxManageInfo.cpp" line="2830"/> + <source>not active</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="401"/> + <source>pre-initializing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="403"/> + <source>initializing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="405"/> + <source>active/running</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="407"/> + <source>terminating</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="409"/> + <source>terminated</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="411"/> + <source>failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="692"/> + <location filename="../VBoxManageInfo.cpp" line="1404"/> + <location filename="../VBoxManageInfo.cpp" line="2139"/> + <source>Null</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="693"/> + <source>Disk</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="694"/> + <location filename="../VBoxManageInfo.cpp" line="1295"/> + <source>Network</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="709"/> + <location filename="../VBoxManageInfo.cpp" line="2693"/> + <source><none> +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="732"/> + <source>#%zu: Name: '%ls', Type: %s, Limit: none (disabled) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="780"/> + <source>#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s (%RI64 %s) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="784"/> + <source>#%zu: Name: '%ls', Type: %s, Limit: %RI64 %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="813"/> + <source>Name: '%ls', Host path: '%ls' (%s), %s%s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="814"/> + <source>writable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="814"/> + <source>readonly</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="815"/> + <source>, auto-mount</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="817"/> + <source>, mount-point: '%ls' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="840"/> + <source>VendorId:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="841"/> + <source>ProductId:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="850"/> + <source>Revision:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="852"/> + <source>Manufacturer:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="853"/> + <source>Product:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="854"/> + <source>SerialNumber:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="855"/> + <source>Address:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="862"/> + <location filename="../VBoxManageInfo.cpp" line="1542"/> + <location filename="../VBoxManageInfo.cpp" line="2572"/> + <location filename="../VBoxManageInfo.cpp" line="2985"/> + <source><none></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="920"/> + <source> Port %u, Unit %u: UUID: %ls%s%s%s%s%s%s + Location: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="922"/> + <source>, passthrough enabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="923"/> + <location filename="../VBoxManageInfo.cpp" line="966"/> + <source>, temp eject</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="924"/> + <location filename="../VBoxManageInfo.cpp" line="967"/> + <source>, ejected</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="925"/> + <source>, hot-pluggable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="926"/> + <source>, non-rotational (SSD)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="927"/> + <source>, discards unused blocks</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="965"/> + <source> Port %u, Unit %u: Empty%s%s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="979"/> + <source> Port %u, Unit %u: GetMedium failed: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="995"/> + <location filename="../VBoxManageInfo.cpp" line="1027"/> + <location filename="../VBoxManageInfo.cpp" line="1914"/> + <location filename="../VBoxManageInfo.cpp" line="1950"/> + <source>None</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1000"/> + <source>Automatic</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1015"/> + <location filename="../VBoxManageInfo.cpp" line="1057"/> + <location filename="../VBoxManageInfo.cpp" line="1428"/> + <location filename="../VBoxManageInfo.cpp" line="1908"/> + <location filename="../VBoxManageInfo.cpp" line="1945"/> + <location filename="../VBoxManageInfo.cpp" line="2124"/> + <location filename="../VBoxManageInfo.cpp" line="2125"/> + <location filename="../VBoxManageInfo.cpp" line="2126"/> + <location filename="../VBoxManageInfo.cpp" line="2269"/> + <location filename="../VBoxManageInfo.cpp" line="2298"/> + <source>Unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1032"/> + <source>Default</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1037"/> + <source>Legacy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1042"/> + <source>Minimal</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1106"/> + <source>"<inaccessible>" {%s} +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1112"/> + <source>Name: <inaccessible!> +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1121"/> + <source>Config file: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1124"/> + <source>Access error details: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1144"/> + <source>Name:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1145"/> + <source>Groups:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1151"/> + <location filename="../VBoxManageInfo.cpp" line="1153"/> + <source>Guest OS:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1155"/> + <source>Config file:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1156"/> + <source>Snapshot folder:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1157"/> + <source>Log folder:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1158"/> + <source>Hardware UUID:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1159"/> + <source>Memory size:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1160"/> + <source>Page Fusion:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1163"/> + <source>VRAM size:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1164"/> + <source>CPU exec cap:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1165"/> + <source>HPET:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1166"/> + <source>CPUProfile:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1177"/> + <source>invalid</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1189"/> + <source>Chipset:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1209"/> + <source>Firmware:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1211"/> + <source>Number of CPUs:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1213"/> + <source>Long Mode:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1214"/> + <source>Triple Fault Reset:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1217"/> + <source>Nested VT-x/AMD-V:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1218"/> + <source>CPUID Portability Level:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1221"/> + <source>CPUID overrides:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1234"/> + <source>Leaf no. EAX EBX ECX EDX +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1246"/> + <source>None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1269"/> + <source>menu only</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1275"/> + <source>message and menu</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1277"/> + <source>Boot menu mode:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1289"/> + <source>Floppy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1293"/> + <source>HardDisk</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1299"/> + <source>Shared Folder</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1301"/> + <source>Not Assigned</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1302"/> + <source>Boot Device %u:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1333"/> + <source>BIOS APIC mode:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1335"/> + <source>Time offset:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1335"/> + <source>ms</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1339"/> + <source>BIOS NVRAM File:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1340"/> + <source>RTC:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1340"/> + <source>local time</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1341"/> + <source>Hardware Virtualization:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1342"/> + <source>Nested Paging:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1343"/> + <source>Large Pages:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1345"/> + <source>VT-x Unrestricted Exec.:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1346"/> + <source>AMD-V Virt. Vmsave/Vmload:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1358"/> + <source>Paravirt. Provider:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1363"/> + <source>Effective Paravirt. Prov.:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1368"/> + <source>Paravirt. Debug:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1391"/> + <source>%-28s %s (since %s) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1391"/> + <source>State:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1435"/> + <source>Graphics Controller:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1438"/> + <source>Monitor count:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1439"/> + <source>3D Acceleration:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1441"/> + <source>2D Video Acceleration:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1443"/> + <source>Teleporter Enabled:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1444"/> + <source>Teleporter Port:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1445"/> + <source>Teleporter Address:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1446"/> + <source>Teleporter Password:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1447"/> + <source>Tracing Enabled:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1448"/> + <source>Allow Tracing to Access VM:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1449"/> + <source>Tracing Configuration:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1450"/> + <source>Autostart Enabled:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1451"/> + <source>Autostart Delay:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1452"/> + <source>Default Frontend:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1463"/> + <source>flat</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1469"/> + <source>low</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1475"/> + <source>normal</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1481"/> + <source>high</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1487"/> + <source>default</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1490"/> + <source>VM process priority:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1502"/> + <location filename="../VBoxManageInfo.cpp" line="1542"/> + <source>Storage Controllers:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1532"/> + <source>#%u: '%ls', Type: %s, Instance: %u, Ports: %u (max %u), %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1534"/> + <source>Bootable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1534"/> + <source>Not bootable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1561"/> + <source>NIC %u:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1570"/> + <location filename="../VBoxManageInfo.cpp" line="1992"/> + <location filename="../VBoxManageInfo.cpp" line="2098"/> + <location filename="../VBoxManageInfo.cpp" line="2459"/> + <location filename="../VBoxManageInfo.cpp" line="2491"/> + <source>%-28s disabled +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1587"/> + <location filename="../VBoxManageInfo.cpp" line="1892"/> + <location filename="../VBoxManageInfo.cpp" line="1897"/> + <source>none</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1655"/> + <source>%sNIC %d Rule(%d): name = %s, protocol = %s, host ip = %s, host port = %s, guest ip = %s, guest port = %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1678"/> + <source>NIC %d Settings: MTU: %d, Socket (send: %d, receive: %d), TCP Window (send:%d, receive: %d) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1694"/> + <source>Bridged Interface '%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1708"/> + <source>Internal Network '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1722"/> + <source>Host-only Interface '%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1737"/> + <source>Generic '%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1766"/> + <source>NAT Network '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1781"/> + <source>Host Only Network '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1797"/> + <source>Cloud Network '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1820"/> + <source>deny</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1821"/> + <source>allow-vms</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1822"/> + <source>allow-all</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1888"/> + <source>%-28s MAC: %ls, Attachment: %s, Cable connected: %s, Trace: %s (file: %ls), Type: %s, Reported speed: %d Mbps, Boot priority: %d, Promisc Policy: %s, Bandwidth group: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1890"/> + <location filename="../VBoxManageInfo.cpp" line="1891"/> + <location filename="../VBoxManageInfo.cpp" line="2452"/> + <location filename="../VBoxManageInfo.cpp" line="2453"/> + <source>on</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1890"/> + <location filename="../VBoxManageInfo.cpp" line="1891"/> + <location filename="../VBoxManageInfo.cpp" line="2452"/> + <location filename="../VBoxManageInfo.cpp" line="2453"/> + <source>off</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1918"/> + <source>PS/2 Mouse</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1922"/> + <source>USB Mouse</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1926"/> + <source>USB Tablet</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1930"/> + <source>USB Tablet and PS/2 Mouse</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1934"/> + <source>USB Multi-Touch</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1940"/> + <source>Pointing Device:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1954"/> + <source>PS/2 Keyboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1958"/> + <source>USB Keyboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1962"/> + <source>USB and PS/2 Keyboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1968"/> + <source>Keyboard Device:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="1982"/> + <source>UART %u:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2011"/> + <location filename="../VBoxManageInfo.cpp" line="2111"/> + <source>%-28s I/O base: %#06x, IRQ: %d</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2019"/> + <source>, disconnected</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2026"/> + <source>, attached to raw file '%ls' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2034"/> + <source>, attached to tcp (%s) '%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2035"/> + <location filename="../VBoxManageInfo.cpp" line="2043"/> + <source>server</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2035"/> + <location filename="../VBoxManageInfo.cpp" line="2043"/> + <source>client</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2042"/> + <source>, attached to pipe (%s) '%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2050"/> + <source>, attached to device '%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2088"/> + <source>LPT %u:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2115"/> + <source>, attached to device '%ls' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2240"/> + <source>Audio:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2242"/> + <source> (Driver: %s, Controller: %s, Codec: %s)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2245"/> + <source>Audio playback:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2246"/> + <source>Audio capture:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2260"/> + <location filename="../VBoxManageInfo.cpp" line="2289"/> + <source>HostToGuest</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2263"/> + <location filename="../VBoxManageInfo.cpp" line="2292"/> + <source>GuestToHost</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2266"/> + <location filename="../VBoxManageInfo.cpp" line="2295"/> + <source>Bidirectional</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2272"/> + <source>Clipboard Mode:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2274"/> + <source>Clipboard file transfers:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2301"/> + <source>Drag and drop Mode:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2312"/> + <source>Session name:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2345"/> + <source>unknown status</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2348"/> + <source>blank</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2353"/> + <source>Video mode:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2394"/> + <source>null</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2400"/> + <source>external</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2406"/> + <source>guest</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2451"/> + <source>%-28s enabled (Address %ls, Ports %ls, MultiConn: %s, ReuseSingleConn: %s, Authentication type: %s) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2455"/> + <source>VRDE port:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2457"/> + <source>%-28s enabled (Quality %ls) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2457"/> + <location filename="../VBoxManageInfo.cpp" line="2459"/> + <source>Video redirection:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2479"/> + <source>%-28s: %-10lS = <not set> +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2479"/> + <location filename="../VBoxManageInfo.cpp" line="2481"/> + <source>VRDE property</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2546"/> + <source>USB Device Filters: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2552"/> + <source>Index:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2553"/> + <source> Active:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2553"/> + <source>yes</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2553"/> + <source>no</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2554"/> + <source> Name:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2555"/> + <source> VendorId:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2556"/> + <source> ProductId:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2557"/> + <source> Revision:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2558"/> + <source> Manufacturer:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2559"/> + <source> Product:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2560"/> + <source> Remote:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2561"/> + <source> Serial Number:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2567"/> + <source>Masked Interfaces:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2572"/> + <source>USB Device Filters:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2580"/> + <source>Available remote USB devices:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2588"/> + <source>Currently attached USB devices:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2604"/> + <source> +Attached physical PCI devices: + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2623"/> + <source> Host device %ls at %s attached as %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2639"/> + <source>Bandwidth groups:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2652"/> + <source>Shared folders:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2662"/> + <source>global mapping</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2674"/> + <source>machine mapping</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2686"/> + <source>transient mapping</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2738"/> + <source>VRDE Connection:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2738"/> + <location filename="../VBoxManageInfo.cpp" line="2828"/> + <location filename="../VBoxManageInfo.cpp" line="2830"/> + <source>active</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2739"/> + <source>Clients so far:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2746"/> + <source>Start time:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2749"/> + <source>Last started:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2751"/> + <source>Last ended:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2761"/> + <source>Sent:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2761"/> + <location filename="../VBoxManageInfo.cpp" line="2763"/> + <location filename="../VBoxManageInfo.cpp" line="2765"/> + <location filename="../VBoxManageInfo.cpp" line="2767"/> + <source>Bytes</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2762"/> + <source>Average speed:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2762"/> + <location filename="../VBoxManageInfo.cpp" line="2766"/> + <source>B/s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2763"/> + <source>Sent total:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2765"/> + <source>Received:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2766"/> + <source>Speed:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2767"/> + <source>Received total:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2771"/> + <source>User name:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2772"/> + <source>Domain:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2773"/> + <source>Client name:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2774"/> + <source>Client IP:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2775"/> + <source>Client version:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2776"/> + <source>Encryption:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2828"/> + <source>Capturing:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2830"/> + <source>Capture audio:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2840"/> + <source>Capture screens:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2841"/> + <source>Capture file:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2843"/> + <source>Capture dimensions:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2844"/> + <source>Capture rate:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2844"/> + <location filename="../VBoxManageInfo.cpp" line="2845"/> + <source>kbps</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2845"/> + <source>Capture FPS:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2846"/> + <source>Capture options:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2863"/> + <source>Description: +%ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2881"/> + <source>VMMDev Testing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2882"/> + <location filename="../VBoxManageInfo.cpp" line="2884"/> + <source>misconfigured</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2907"/> + <source>* Snapshots: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2916"/> + <source>* Guest: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2919"/> + <source>Configured memory balloon:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2919"/> + <source>MB</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2927"/> + <source>OS type:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2932"/> + <source>Additions run level:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2944"/> + <source>Additions version:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2953"/> + <location filename="../VBoxManageInfo.cpp" line="2985"/> + <source>Guest Facilities:</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="2973"/> + <source>Facility "%ls": %s (last update: %s) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="3044"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="3054"/> + <source>VM name or UUID required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageInfo.cpp" line="3065"/> + <source>Option --log is exclusive</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Internal</name> + <message> + <location filename="../VBoxInternalManage.cpp" line="169"/> + <source>Usage: VBoxManage internalcommands <command> [command arguments] + +Commands: + +%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%sWARNING: This is a development tool and shall only be used to analyse + problems. It is completely unsupported and will change in + incompatible ways without warning. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="180"/> + <source> loadmap <vmname|uuid> <symfile> <address> [module] [subtrahend] [segment] + This will instruct DBGF to load the given map file + during initialization. (See also loadmap in the debugger.) + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="187"/> + <source> loadsyms <vmname|uuid> <symfile> [delta] [module] [module address] + This will instruct DBGF to load the given symbol file + during initialization. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="194"/> + <source> sethduuid <filepath> [<uuid>] + Assigns a new UUID to the given image file. This way, multiple copies + of a container can be registered. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="201"/> + <source> sethdparentuuid <filepath> <uuid> + Assigns a new parent UUID to the given image file. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="207"/> + <source> dumphdinfo <filepath> + Prints information about the image at the given location. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="213"/> + <source> listpartitions -rawdisk <diskname> + Lists all partitions on <diskname>. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="219"/> + <source> createrawvmdk -filename <filename> -rawdisk <diskname> + [-partitions <list of partition numbers> [-mbr <filename>] ] + [-relative] + Creates a new VMDK image which gives access to an entire host disk (if + the parameter -partitions is not specified) or some partitions of a + host disk. If access to individual partitions is granted, then the + parameter -mbr can be used to specify an alternative MBR to be used + (the partitioning information in the MBR file is ignored). + The diskname is on Linux e.g. /dev/sda, and on Windows e.g. + \\.\PhysicalDrive0). + On Linux or FreeBSD host the parameter -relative causes a VMDK file to + be created which refers to individual partitions instead to the entire + disk. + The necessary partition numbers can be queried with + VBoxManage internalcommands listpartitions + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="238"/> + <source> renamevmdk -from <filename> -to <filename> + Renames an existing VMDK image, including the base file and all its extents. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="245"/> + <source> converttoraw [-format <fileformat>] <filename> <outputfile>|stdout + Convert image to raw, writing to file or stdout. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="251"/> + <source> converttoraw [-format <fileformat>] <filename> <outputfile> + Convert image to raw, writing to file. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="259"/> + <source> converthd [-srcformat VDI|VMDK|VHD|RAW] + [-dstformat VDI|VMDK|VHD|RAW] + <inputfile> <outputfile> + converts hard disk images between formats + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="267"/> + <source> repairhd [-dry-run] + [-format VDI|VMDK|VHD|...] + <filename> + Tries to repair corrupted disk images + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="276"/> + <source> modinstall + Installs the necessary driver for the host OS + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="282"/> + <source> moduninstall + Deinstalls the driver + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="292"/> + <source> debuglog <vmname|uuid> [--enable|--disable] [--flags todo] + [--groups todo] [--destinations todo] + Controls debug logging. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="299"/> + <source> passwordhash <password> + Generates a password hash. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="305"/> + <source> gueststats <vmname|uuid> [--interval <seconds>] + Obtains and prints internal guest statistics. + Sets the update interval if specified. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="451"/> + <source>Cannot find unique key for '%s'!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="514"/> + <source>Failed to delete key '%s' from '%s', string conversion error %Rrc!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="538"/> + <source>Failed to set '%s/%s/%s' to '%s'! hrc=%#x</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="606"/> + <location filename="../VBoxInternalManage.cpp" line="683"/> + <source>Missing the filename argument! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="614"/> + <source>Failed to read delta '%s', rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="626"/> + <location filename="../VBoxInternalManage.cpp" line="691"/> + <source>Failed to read module address '%s', rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="634"/> + <source>Failed to read module size '%s', rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="688"/> + <source>Missing the module address argument! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="702"/> + <source>Failed to read subtrahend '%s', rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="710"/> + <source>Failed to read segment number '%s', rc=%Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="737"/> + <source>Error code %Rrc at %s(%u) in function %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="760"/> + <location filename="../VBoxInternalManage.cpp" line="774"/> + <location filename="../VBoxInternalManage.cpp" line="832"/> + <source>Not enough parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="765"/> + <location filename="../VBoxInternalManage.cpp" line="776"/> + <source>Invalid UUID parameter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="780"/> + <source>Invalid invocation</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="788"/> + <location filename="../VBoxInternalManage.cpp" line="841"/> + <source>Format autodetect failed: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="803"/> + <location filename="../VBoxInternalManage.cpp" line="856"/> + <location filename="../VBoxInternalManage.cpp" line="1958"/> + <location filename="../VBoxInternalManage.cpp" line="2056"/> + <location filename="../VBoxInternalManage.cpp" line="2130"/> + <source>Cannot create the virtual disk container: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="808"/> + <location filename="../VBoxInternalManage.cpp" line="861"/> + <source>Cannot open the image: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="815"/> + <source>Cannot set a new UUID: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="817"/> + <source>UUID changed to: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="942"/> + <source>The GPT header seems corrupt because it contains too many entries</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="949"/> + <source>Allocating memory for the GPT partitions entries failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="958"/> + <source>Reading the partition table failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1042"/> + <source>More than one extended partition</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1060"/> + <source>Inconsistency for logical partition start</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1072"/> + <source>Logical partition without magic</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1079"/> + <source>Logical partition with type 0 encountered</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1096"/> + <source>Invalid partition start offset</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1116"/> + <source>Logical partition chain broken</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1139"/> + <source>Two partitions start at the same place</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1144"/> + <source>Partition starts at sector 0</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1180"/> + <source>Overlapping GPT partitions</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1196"/> + <source>Overlapping MBR partitions</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1219"/> + <location filename="../VBoxInternalManage.cpp" line="1304"/> + <location filename="../VBoxInternalManage.cpp" line="1313"/> + <location filename="../VBoxInternalManage.cpp" line="1322"/> + <location filename="../VBoxInternalManage.cpp" line="1331"/> + <location filename="../VBoxInternalManage.cpp" line="2018"/> + <location filename="../VBoxInternalManage.cpp" line="2027"/> + <location filename="../VBoxInternalManage.cpp" line="2088"/> + <location filename="../VBoxInternalManage.cpp" line="2251"/> + <location filename="../VBoxInternalManage.cpp" line="2260"/> + <location filename="../VBoxInternalManage.cpp" line="2385"/> + <source>Missing argument to '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="368"/> + <location filename="../VBoxInternalManage.cpp" line="1226"/> + <location filename="../VBoxInternalManage.cpp" line="1343"/> + <location filename="../VBoxInternalManage.cpp" line="2034"/> + <location filename="../VBoxInternalManage.cpp" line="2107"/> + <location filename="../VBoxInternalManage.cpp" line="2275"/> + <location filename="../VBoxInternalManage.cpp" line="2396"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="327"/> + <source> +Syntax error: %N +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="372"/> + <source>Invalid option -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="373"/> + <source>Invalid option case %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="376"/> + <source>Unknown option: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="378"/> + <source>Invalid argument format: %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1231"/> + <location filename="../VBoxInternalManage.cpp" line="1349"/> + <source>Mandatory parameter -rawdisk missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1236"/> + <source>Cannot open the raw disk: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1242"/> + <source>Number Type StartCHS EndCHS Size (MiB) Start (Sect) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1347"/> + <source>Mandatory parameter -filename missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1352"/> + <source>The parameter -mbr is only valid when the parameter -partitions is also present</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1361"/> + <source>Cannot open the raw disk '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1390"/> + <source>File '%s' is no fixed/removable medium device</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1407"/> + <source>The -relative parameter is invalid for raw disk %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1421"/> + <source>Cannot get the geometry of the raw disk '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1428"/> + <location filename="../VBoxInternalManage.cpp" line="1477"/> + <location filename="../VBoxInternalManage.cpp" line="1602"/> + <source>The -relative parameter is invalid for raw images</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1462"/> + <location filename="../VBoxInternalManage.cpp" line="1556"/> + <location filename="../VBoxInternalManage.cpp" line="1627"/> + <source>Cannot get the size of the raw disk '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1472"/> + <location filename="../VBoxInternalManage.cpp" line="1527"/> + <location filename="../VBoxInternalManage.cpp" line="1565"/> + <source>Failed to get size of file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1484"/> + <source>File '%s' is no block device</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1492"/> + <location filename="../VBoxInternalManage.cpp" line="1541"/> + <location filename="../VBoxInternalManage.cpp" line="1579"/> + <location filename="../VBoxInternalManage.cpp" line="1618"/> + <source>Failed to get file informtation for raw disk '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1509"/> + <source>Cannot get the block size for file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1517"/> + <location filename="../VBoxInternalManage.cpp" line="1594"/> + <source>Cannot get the block count for file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1533"/> + <source>File '%s' is neither block device nor regular file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1571"/> + <source>File '%s' is no block or char device</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1610"/> + <source>File '%s' is neither character device nor regular file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1635"/> + <source>Detected size of raw disk '%s' is %RU64, an invalid value</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1667"/> + <source>Incorrect value in partitions parameter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1681"/> + <source>Incorrect separator in partitions parameter</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1691"/> + <source>Cannot read the partition information from '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1706"/> + <source>It is not possible (and necessary) to explicitly give access to the extended partition %u. If required, enable access to all logical partitions inside this extended partition.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1726"/> + <location filename="../VBoxInternalManage.cpp" line="1794"/> + <source>Out of memory allocating the partition list for '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1742"/> + <source>Out of memory allocating the partition descriptor for '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1751"/> + <source>Cannot read partition data from raw device '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1763"/> + <source>Cannot open replacement MBR file '%s' specified with -mbr: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1771"/> + <source>Cannot read replacement MBR file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1837"/> + <source>Cannot create reference to individual partition %u, rc=%Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1852"/> + <source>Cannot create reference to individual partition %u (numbered %u), rc=%Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1914"/> + <source>MBR/EPT overlaps with data area</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1920"/> + <source>GPT overlaps with data area</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1977"/> + <source>Cannot create the raw disk VMDK: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="1980"/> + <source>RAW host disk access VMDK file %s created successfully. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2002"/> + <source>The raw disk vmdk file was not created</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2039"/> + <source>Mandatory parameter -from missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2041"/> + <source>Mandatory parameter -to missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2065"/> + <source>Cannot rename the image: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2068"/> + <source>Cannot create the source image: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2112"/> + <source>Mandatory filename parameter missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2114"/> + <source>Mandatory outputfile parameter missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2142"/> + <source>Cannot create destination file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2161"/> + <location filename="../VBoxInternalManage.cpp" line="2304"/> + <location filename="../VBoxInternalManage.cpp" line="2424"/> + <source>No file format specified and autodetect failed - please specify format: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2164"/> + <source>Only converting harddisk images is supported</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2179"/> + <location filename="../VBoxInternalManage.cpp" line="2323"/> + <source>Cannot open the source image: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxInternalManage.cpp" line="2189"/> + <source>Converting image "%s" with size %RU64 bytes (%RU64MB) to raw... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2211"/> + <source>Cannot copy image data: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2223"/> + <source>Out of memory allocating read buffer</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2280"/> + <location filename="../VBoxInternalManage.cpp" line="2401"/> + <source>Mandatory input image parameter missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2282"/> + <source>Mandatory output image parameter missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2315"/> + <source>Cannot create the source virtual disk container: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2334"/> + <source>Cannot create the destination virtual disk container: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxInternalManage.cpp" line="2339"/> + <source>Converting image "%s" with size %RU64 bytes (%RU64MB)... +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2348"/> + <source>Cannot copy the image: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2476"/> + <location filename="../VBoxInternalManage.cpp" line="2611"/> + <source>Missing VM name/UUID</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2576"/> + <source>One or more of the requested features are not implemented! Feel free to do this.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2592"/> + <source>password to hash required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2598"/> + <source>Password hash: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2641"/> + <source>Invalid update interval specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2643"/> + <source>argc=%d interval=%u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2694"/> + <source>Command missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxInternalManage.cpp" line="2734"/> + <source>Invalid command '%s'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>List</name> + <message> + <location filename="../VBoxManageList.cpp" line="54"/> + <location filename="../VBoxManageList.cpp" line="68"/> + <location filename="../VBoxManageList.cpp" line="94"/> + <location filename="../VBoxManageList.cpp" line="853"/> + <location filename="../VBoxManageList.cpp" line="864"/> + <source>Unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="59"/> + <location filename="../VBoxManageList.cpp" line="73"/> + <source>unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="66"/> + <source>Up</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="67"/> + <source>Down</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="81"/> + <source>HardDisk</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="83"/> + <source>Floppy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="86"/> + <source>Network</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="88"/> + <source>SharedFolder</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="89"/> + <source>Graphics3D</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="111"/> + <location filename="../VBoxManageList.cpp" line="149"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="156"/> + <location filename="../VBoxManageList.cpp" line="215"/> + <location filename="../VBoxManageList.cpp" line="261"/> + <location filename="../VBoxManageList.cpp" line="1340"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="162"/> + <location filename="../VBoxManageList.cpp" line="221"/> + <location filename="../VBoxManageList.cpp" line="267"/> + <source>Enabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="162"/> + <location filename="../VBoxManageList.cpp" line="221"/> + <location filename="../VBoxManageList.cpp" line="267"/> + <source>Disabled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="166"/> + <source>IPAddress: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="169"/> + <location filename="../VBoxManageList.cpp" line="225"/> + <source>NetworkMask: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="172"/> + <source>IPV6Address: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="175"/> + <source>IPV6NetworkMaskPrefixLength: %d +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="178"/> + <source>HardwareAddress: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="181"/> + <source>MediumType: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="184"/> + <source>Wireless: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="184"/> + <location filename="../VBoxManageList.cpp" line="1069"/> + <source>Yes</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="184"/> + <location filename="../VBoxManageList.cpp" line="1069"/> + <source>No</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="187"/> + <source>Status: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="190"/> + <location filename="../VBoxManageList.cpp" line="236"/> + <location filename="../VBoxManageList.cpp" line="279"/> + <source>VBoxNetworkName: %ls + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="221"/> + <location filename="../VBoxManageList.cpp" line="267"/> + <source>State: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="228"/> + <source>LowerIP: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="231"/> + <source>UpperIP: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="271"/> + <source>CloudProvider: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="274"/> + <source>CloudProfile: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="277"/> + <source>CloudNetworkId: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="301"/> + <source>HW virtualization</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="303"/> + <source>long mode</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="304"/> + <source>nested paging</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="305"/> + <source>unrestricted guest</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="306"/> + <source>nested HW virtualization</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="307"/> + <source>virt. vmsave/vmload</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="313"/> + <source>Host Information: + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="319"/> + <source>Host time: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="323"/> + <source>Processor online count: %lu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="326"/> + <source>Processor count: %lu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="329"/> + <source>Processor online core count: %lu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="332"/> + <source>Processor core count: %lu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="337"/> + <source>Processor supports %s: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="337"/> + <location filename="../VBoxManageList.cpp" line="671"/> + <location filename="../VBoxManageList.cpp" line="825"/> + <location filename="../VBoxManageList.cpp" line="889"/> + <location filename="../VBoxManageList.cpp" line="1803"/> + <location filename="../VBoxManageList.cpp" line="1808"/> + <source>yes</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="337"/> + <location filename="../VBoxManageList.cpp" line="671"/> + <location filename="../VBoxManageList.cpp" line="825"/> + <location filename="../VBoxManageList.cpp" line="889"/> + <location filename="../VBoxManageList.cpp" line="1803"/> + <location filename="../VBoxManageList.cpp" line="1808"/> + <source>no</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="344"/> + <source>Processor#%u speed: %lu MHz +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="346"/> + <source>Processor#%u speed: unknown +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="349"/> + <source>Processor#%u description: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="354"/> + <source>Memory size: %lu MByte +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="358"/> + <source>Memory available: %lu MByte +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="362"/> + <source>Operating system: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="366"/> + <source>Operating system version: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="424"/> + <source>Supported hard disk backends: + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="443"/> + <source>Backend %u: id='%ls' description='%ls' capabilities=%#06x extensions='</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="472"/> + <source> properties=(</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="477"/> + <source> + name='%ls' desc='%ls' type=</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="481"/> + <source>int</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="482"/> + <source>byte</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="483"/> + <source>string</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="488"/> + <source> flags=%#04x</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="489"/> + <source> default='%ls'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="515"/> + <source>Host USB Devices: + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="519"/> + <location filename="../VBoxManageList.cpp" line="657"/> + <source><none> + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="543"/> + <source>UUID: %s +VendorId: %#06x (%04X) +ProductId: %#06x (%04X) +Revision: %u.%u (%02u%02u) +Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="559"/> + <source>Low</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="562"/> + <source>Full</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="565"/> + <source>High</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="568"/> + <source>Super</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="571"/> + <source>SuperPlus</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="578"/> + <source>USB version/speed: %u/%s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="587"/> + <source>Manufacturer: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="591"/> + <source>Product: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="594"/> + <source>SerialNumber: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="597"/> + <source>Address: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="600"/> + <source>Port path: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="609"/> + <source>Not supported</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="612"/> + <source>Unavailable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="615"/> + <source>Busy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="618"/> + <source>Available</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="621"/> + <source>Held</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="624"/> + <source>Captured</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="630"/> + <source>Current State: %s + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="647"/> + <source>Global USB Device Filters: + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="667"/> + <source>Index: %zu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="671"/> + <source>Active: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="675"/> + <source><invalid></source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="679"/> + <source>Ignore</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="682"/> + <source>Hold</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="687"/> + <source>Action: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="691"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="693"/> + <source>VendorId: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="695"/> + <source>ProductId: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="697"/> + <source>Revision: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="699"/> + <source>Manufacturer: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="701"/> + <source>Product: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="703"/> + <source>Serial Number: %ls + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="728"/> + <source>API version: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="731"/> + <source>Minimum guest RAM size: %u Megabytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="733"/> + <source>Maximum guest RAM size: %u Megabytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="735"/> + <source>Minimum video RAM size: %u Megabytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="737"/> + <source>Maximum video RAM size: %u Megabytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="739"/> + <source>Maximum guest monitor count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="741"/> + <source>Minimum guest CPU count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="743"/> + <source>Maximum guest CPU count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="745"/> + <source>Virtual disk limit (info): %lld Bytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="747"/> + <source>Maximum Serial Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="749"/> + <source>Maximum Parallel Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="751"/> + <source>Maximum Boot Position: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="753"/> + <source>Maximum PIIX3 Network Adapter count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="755"/> + <source>Maximum ICH9 Network Adapter count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="757"/> + <source>Maximum PIIX3 IDE Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="759"/> + <source>Maximum ICH9 IDE Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="761"/> + <source>Maximum IDE Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="763"/> + <source>Maximum Devices per IDE Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="765"/> + <source>Maximum PIIX3 SATA Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="767"/> + <source>Maximum ICH9 SATA Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="769"/> + <source>Maximum SATA Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="771"/> + <source>Maximum Devices per SATA Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="773"/> + <source>Maximum PIIX3 SCSI Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="775"/> + <source>Maximum ICH9 SCSI Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="777"/> + <source>Maximum SCSI Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="779"/> + <source>Maximum Devices per SCSI Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="781"/> + <source>Maximum SAS PIIX3 Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="783"/> + <source>Maximum SAS ICH9 Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="785"/> + <source>Maximum SAS Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="787"/> + <source>Maximum Devices per SAS Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="789"/> + <source>Maximum NVMe PIIX3 Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="791"/> + <source>Maximum NVMe ICH9 Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="793"/> + <source>Maximum NVMe Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="795"/> + <source>Maximum Devices per NVMe Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="797"/> + <source>Maximum virtio-scsi PIIX3 Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="799"/> + <source>Maximum virtio-scsi ICH9 Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="801"/> + <source>Maximum virtio-scsi Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="803"/> + <source>Maximum Devices per virtio-scsi Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="805"/> + <source>Maximum PIIX3 Floppy Controllers:%u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="807"/> + <source>Maximum ICH9 Floppy Controllers: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="809"/> + <source>Maximum Floppy Port count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="811"/> + <source>Maximum Devices per Floppy Port: %u +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="814"/> + <source>Free disk space warning at: %u Bytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="816"/> + <source>Free disk space warning at: %u %% +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="818"/> + <source>Free disk space error at: %u Bytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="820"/> + <source>Free disk space error at: %u %% +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="823"/> + <source>Default machine folder: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="825"/> + <source>Raw-mode Supported: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="827"/> + <source>Exclusive HW virtualization use: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="827"/> + <location filename="../VBoxManageList.cpp" line="1867"/> + <location filename="../VBoxManageList.cpp" line="1871"/> + <source>on</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="827"/> + <location filename="../VBoxManageList.cpp" line="1867"/> + <location filename="../VBoxManageList.cpp" line="1871"/> + <source>off</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="829"/> + <source>Default hard disk format: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="831"/> + <source>VRDE auth library: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="833"/> + <source>Webservice auth. library: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="835"/> + <source>Remote desktop ExtPack: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="837"/> + <source>Log history count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="839"/> + <source>Default frontend: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="844"/> + <source>Null</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="855"/> + <source>Default audio driver: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="857"/> + <source>Autostart database path: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="859"/> + <source>Default Guest Additions ISO: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="861"/> + <source>Logging Level: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="867"/> + <source>System</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="868"/> + <source>NoProxy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="869"/> + <source>Manual</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="874"/> + <source>Proxy Mode: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="876"/> + <source>Proxy URL: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="908"/> + <source>Stable: new minor and maintenance releases</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="911"/> + <source>All releases: new minor, maintenance, and major releases</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="914"/> + <source>With Betas: new minor, maintenance, major, and beta releases</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="917"/> + <source>Unset</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="924"/> + <source>Last check date: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="879"/> + <source>User language: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="889"/> + <source>Enabled: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="892"/> + <source>Check count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="895"/> + <source>Check frequency: never +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="897"/> + <source>Check frequency: every day +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="899"/> + <source>Check frequency: every %u days +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="920"/> + <source>Channel: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="922"/> + <source>Repository: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="952"/> + <source> minLeaseTime: default +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="954"/> + <source> minLeaseTime: %u sec +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="959"/> + <source> defaultLeaseTime: default +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="961"/> + <source> defaultLeaseTime: %u sec +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="966"/> + <source> maxLeaseTime: default +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="968"/> + <source> maxLeaseTime: %u sec +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="974"/> + <source> Forced options: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="976"/> + <source> Forced options: None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="979"/> + <source> Forced options: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="987"/> + <source> Suppressed opt.s: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="989"/> + <source> Suppressed opts.: None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="992"/> + <source> Suppressed opts.: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1004"/> + <source> DHCP options: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1007"/> + <source> DHCP options: Return count mismatch: %zu, %zu, %zu +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1012"/> + <source> DHCP options: None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1019"/> + <source> %3d/legacy: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1053"/> + <source>NetworkName: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1059"/> + <source>LowerIPAddress: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1062"/> + <source>UpperIPAddress: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1065"/> + <source>NetworkMask: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1069"/> + <source>Enabled: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1072"/> + <source>Global Configuration: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1087"/> + <source>Groups: %Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1089"/> + <source>Groups: None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1095"/> + <source>Group: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1100"/> + <source> Conditions: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1102"/> + <source> Conditions: None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1112"/> + <source> Conditions: %s %s %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1113"/> + <source>include</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1113"/> + <source>exclude</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1135"/> + <source>Individual Configs: %Rrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1137"/> + <source>Individual Configs: None +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1148"/> + <source>Individual Config: MAC %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1158"/> + <source>Individual Config: VM NIC: %ls slot %u, MAC %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1161"/> + <source>Individual Config: VM NIC: %ls slot %u, MAC %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1166"/> + <source> Fixed Address: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1168"/> + <source> Fixed Address: dynamic +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1194"/> + <source>Extension Packs: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1220"/> + <source>Pack no.%2zu: %ls +Version: %ls +Revision: %u +Edition: %ls +Description: %ls +VRDE Module: %ls +Usable: %RTbool +Why unusable: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1276"/> + <source>Video Input Devices: %u +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1305"/> + <source>Supported %d screen shot formats: +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1334"/> + <source>Supported %d cloud providers: +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1342"/> + <source>Short Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1378"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1381"/> + <source>Provider GUID: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1397"/> + <source>Property: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1435"/> + <source>CPU Profile #%02zu: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1436"/> + <source> Architecture: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1437"/> + <source> Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1439"/> + <source> Full Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1689"/> + <source>%sDrive: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1691"/> + <source>%sDrive: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1696"/> + <source>Model: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1698"/> + <source>Model: "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1700"/> + <source>Model: unknown/inaccessible +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1710"/> + <source>Further disk and partitioning information is not available for drive "%ls". (E_ACCESSDENIED) +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1723"/> + <source>Size: %llu bytes (%Rhcb) +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1725"/> + <source>Size: %Rhcb +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1728"/> + <source>Size: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageList.cpp" line="1735"/> + <source>Sector Size: %u bytes +</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1738"/> + <source>Sector Size: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1745"/> + <source>Scheme: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1748"/> + <source>Scheme: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1756"/> + <source>Partitions: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1760"/> + <source>Partitions: None (or not able to grok them). +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1764"/> + <source>Partitions: First Last +## Type Byte Size Byte Offset Cyl/Head/Sec Cyl/Head/Sec Active +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1767"/> + <source>Partitions: First Last +## Type Size Start Cyl/Head/Sec Cyl/Head/Sec Active +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1826"/> + <source>Partitions: +## %-*s Uuid Byte Size Byte Offset Active Name +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1829"/> + <location filename="../VBoxManageList.cpp" line="1834"/> + <source>Type</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="1831"/> + <source>Partitions: +## %-*s Uuid Size Start Active Name +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2043"/> + <source>Description: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2046"/> + <source>Family ID: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2049"/> + <source>Family Desc: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2052"/> + <source>64 bit: %RTbool +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2075"/> + <location filename="../VBoxManageList.cpp" line="2097"/> + <source>Name: %ls + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2134"/> + <source>Host CPUIDs: + +Leaf no. EAX EBX ECX EDX +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2166"/> + <source>base</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2388"/> + <source>Unknown subcommand "%s".</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageList.cpp" line="2399"/> + <source>Missing subcommand for "list" command. +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Metrics</name> + <message> + <location filename="../VBoxManageMetrics.cpp" line="90"/> + <source>Invalid machine name: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="128"/> + <source>host</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="138"/> + <source>unknown</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="149"/> + <source>The following metrics were modified: + +Object Metric +---------- -------------------- +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="163"/> + <source>No metrics match the specified filter!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="197"/> + <source>Object Metric Unit Minimum Maximum Period Count Description +--------------- ---------------------------------------- ---- ---------- ---------- ---------- ---------- ----------- +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="240"/> + <location filename="../VBoxManageMetrics.cpp" line="249"/> + <location filename="../VBoxManageMetrics.cpp" line="412"/> + <location filename="../VBoxManageMetrics.cpp" line="421"/> + <source>Missing argument to '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="243"/> + <location filename="../VBoxManageMetrics.cpp" line="415"/> + <source>Invalid value for 'period' parameter: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="252"/> + <location filename="../VBoxManageMetrics.cpp" line="424"/> + <source>Invalid value for 'samples' parameter: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="319"/> + <source>Object Metric Values +--------------- ---------------------------------------- -------------------------------------------- +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="483"/> + <source>The background process holding collected metrics will shutdown +in few seconds, discarding all collected data and parameters.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="492"/> + <source>Time stamp Object Metric Value +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="639"/> + <source>Subcommand missing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMetrics.cpp" line="658"/> + <source>Invalid subcommand '%s'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Misc</name> + <message> + <location filename="../VBoxManageMisc.cpp" line="66"/> + <location filename="../VBoxManageMisc.cpp" line="760"/> + <location filename="../VBoxManageMisc.cpp" line="789"/> + <location filename="../VBoxManageMisc.cpp" line="824"/> + <location filename="../VBoxManageMisc.cpp" line="950"/> + <source>Incorrect number of parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="79"/> + <location filename="../VBoxManageMisc.cpp" line="799"/> + <source>Cannot convert filename "%s" to absolute path: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="125"/> + <location filename="../VBoxManageMisc.cpp" line="354"/> + <location filename="../VBoxManageMisc.cpp" line="530"/> + <location filename="../VBoxManageMisc.cpp" line="1075"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="132"/> + <location filename="../VBoxManageMisc.cpp" line="683"/> + <source>Invalid option -%c</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="133"/> + <location filename="../VBoxManageMisc.cpp" line="685"/> + <source>Invalid option case %i</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="136"/> + <location filename="../VBoxManageMisc.cpp" line="688"/> + <source>unknown option: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="139"/> + <location filename="../VBoxManageMisc.cpp" line="692"/> + <source>error: %Rrs</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="145"/> + <location filename="../VBoxManageMisc.cpp" line="370"/> + <location filename="../VBoxManageMisc.cpp" line="540"/> + <source>VM name required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="162"/> + <source>Machine delete failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="256"/> + <source>Parameter --name is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="298"/> + <source>Virtual machine '%ls' is created%s. +UUID: %s +Settings file: '%ls' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="301"/> + <source> and registered</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="343"/> + <location filename="../VBoxManageMisc.cpp" line="1388"/> + <source>RTPathAbs(%s,,) failed with rc=%Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="394"/> + <source>Move VM failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="399"/> + <source>Machine has been successfully moved into %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="400"/> + <source>the same location</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="510"/> + <source>Invalid clone mode '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="515"/> + <source>Invalid clone options '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="562"/> + <source>%s Clone</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="596"/> + <source>Clone VM failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="603"/> + <source>Machine has been successfully cloned as "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="672"/> + <source>Parameter to option --putenv must not contain any newline character</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="698"/> + <source>at least one VM name or uuid required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="716"/> + <source>Waiting for VM "%s" to power on... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="731"/> + <source>VM "%s" has been successfully started. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="844"/> + <location filename="../VBoxManageMisc.cpp" line="880"/> + <source>Key: %ls, Value: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="853"/> + <location filename="../VBoxManageMisc.cpp" line="889"/> + <source>Value: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="855"/> + <location filename="../VBoxManageMisc.cpp" line="891"/> + <source>No value set! +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="903"/> + <location filename="../VBoxManageMisc.cpp" line="1315"/> + <source>Not enough parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="916"/> + <location filename="../VBoxManageMisc.cpp" line="938"/> + <source>Too many parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="972"/> + <source>Invalid hwvirtexclusive argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="979"/> + <source>Warning: 'vrdpauthlibrary' is deprecated. Use 'vrdeauthlibrary'. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1009"/> + <source>Error parsing Log history count '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1044"/> + <source>Unknown proxy mode: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1138"/> + <location filename="../VBoxManageMisc.cpp" line="1250"/> + <source>Machine name is given more than once: first '%s', then '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1148"/> + <location filename="../VBoxManageMisc.cpp" line="1260"/> + <source>No machine was specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1151"/> + <location filename="../VBoxManageMisc.cpp" line="1262"/> + <source>No shared folder name (--name) was given</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1153"/> + <source>Invalid shared folder name '%s': contains space</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1155"/> + <source>Invalid shared folder name '%s': contains tabs</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1157"/> + <source>Invalid shared folder name '%s': contains newline</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1160"/> + <source>No host path (--hostpath) was given</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1164"/> + <source>RTAbsPath failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1187"/> + <source>Machine '%s' is not currently running.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1283"/> + <source>Machine '%s' is not currently running. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1374"/> + <location filename="../VBoxManageMisc.cpp" line="1459"/> + <source>Too many extension pack names given to "extpack uninstall"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1383"/> + <source>No extension pack name was given to "extpack install"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1412"/> + <source>License accepted. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1416"/> + <source>Do you agree to these license terms and conditions (y/n)? </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1421"/> + <source>Installation of "%ls" aborted. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1425"/> + <source>License accepted. For batch installation add +--accept-license=%s +to the VBoxManage command line. + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1433"/> + <source>Failed to install "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1435"/> + <source>Successfully installed "%ls". +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1468"/> + <source>No extension pack name was given to "extpack uninstall"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1474"/> + <source>Failed to uninstall "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1476"/> + <source>Successfully uninstalled "%s". +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1484"/> + <source>Successfully performed extension pack cleanup +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1526"/> + <location filename="../VBoxManageMisc.cpp" line="1679"/> + <location filename="../VBoxManageMisc.cpp" line="1718"/> + <location filename="../VBoxManageMisc.cpp" line="1731"/> + <location filename="../VBoxManageMisc.cpp" line="1766"/> + <location filename="../VBoxManageMisc.cpp" line="1777"/> + <location filename="../VBoxManageMisc.cpp" line="1784"/> + <source>RTPathAbs failed on '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1542"/> + <source>No ISO specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1587"/> + <source>Detected '%s' to be: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1588"/> + <source> OS TypeId = %ls + OS Version = %ls + OS Flavor = %ls + OS Languages = %ls + OS Hints = %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1671"/> + <source>VM name/UUID given more than once!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1813"/> + <source>Missing VM name/UUID</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1865"/> + <source>Machine '%ls' is currently running</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1871"/> + <source>%s unattended installation of %s in machine '%ls' (%ls). +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1872"/> + <source>Preparing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1872"/> + <source>Starting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1885"/> + <source>Using values: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1892"/> + <location filename="../VBoxManageMisc.cpp" line="1900"/> + <location filename="../VBoxManageMisc.cpp" line="1952"/> + <source> %32s = failed: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1955"/> + <source> %32 = failed: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1971"/> + <source>VM '%ls' (%ls) is ready to be started (e.g. VBoxManage startvm). +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="1990"/> + <source>Waiting for VM '%ls' to power on... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2005"/> + <source>VM '%ls' (%ls) has been successfully started. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2137"/> + <location filename="../VBoxManageMisc.cpp" line="2187"/> + <location filename="../VBoxManageMisc.cpp" line="2247"/> + <location filename="../VBoxManageMisc.cpp" line="2345"/> + <source>Parameter --provider is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2139"/> + <location filename="../VBoxManageMisc.cpp" line="2189"/> + <location filename="../VBoxManageMisc.cpp" line="2249"/> + <location filename="../VBoxManageMisc.cpp" line="2347"/> + <source>Parameter --profile is required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2168"/> + <source>Provider %ls: profile '%ls' was updated. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2210"/> + <source>Provider GUID: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2226"/> + <source>Property: </source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2331"/> + <source>Provider %ls: profile '%ls' was added. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageMisc.cpp" line="2374"/> + <source>Provider %ls: profile '%ls' was deleted. +</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>ModifyVM</name> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="467"/> + <source>Warning: '--vrdp%s' is deprecated. Use '--vrde%s'. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="578"/> + <source>Invalid %s number %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="607"/> + <location filename="../VBoxManageModifyVM.cpp" line="2089"/> + <source>Not enough parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="670"/> + <source>Cannot open file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="678"/> + <source>Cannot get size of file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="684"/> + <source>File "%s" is bigger than 256KByte</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="692"/> + <source>Cannot read contents of file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="743"/> + <source>Invalid --firmware argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="814"/> + <source>Invalid --paravirtprovider argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="841"/> + <location filename="../VBoxManageModifyVM.cpp" line="1989"/> + <location filename="../VBoxManageModifyVM.cpp" line="2381"/> + <location filename="../VBoxManageModifyVM.cpp" line="2460"/> + <location filename="../VBoxManageModifyVM.cpp" line="2503"/> + <location filename="../VBoxManageModifyVM.cpp" line="2939"/> + <source>Missing or invalid argument to '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="985"/> + <source>Invalid --graphicscontroller argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1051"/> + <source>Invalid --biosbootmenu argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1075"/> + <source>Invalid --biosapic argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1122"/> + <source>Invalid boot device '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1202"/> + <source>Invalid --idecontroller argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1232"/> + <source>Invalid --usb argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1307"/> + <source>Invalid --scsitype argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1362"/> + <location filename="../VBoxManageModifyVM.cpp" line="1370"/> + <source>Invalid host DVD drive name "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1436"/> + <source>Invalid host floppy drive name "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1516"/> + <source>Invalid --nicproperty%d argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1523"/> + <source>Error: Failed to allocate memory for --nicproperty%d '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1597"/> + <source>Invalid NIC type '%s' specified for NIC %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1632"/> + <source>Invalid boot priority '%u' specfied for NIC %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1654"/> + <source>Unknown promiscuous mode policy '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="1789"/> + <source>Invalid type '%s' specfied for NIC %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2073"/> + <source>Invalid proto '%s' specfied for NIC %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2291"/> + <source>Invalid type '%s' specfied for pointing device</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2336"/> + <source>Invalid type '%s' specfied for keyboard</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2439"/> + <source>Invalid argument to '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2467"/> + <source>Error parsing UART I/O base '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2510"/> + <source>Error parsing LPT I/O base '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2539"/> + <source>Invalid --audiocontroller argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2561"/> + <source>Invalid --audiocodec argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2633"/> + <source>Invalid --audio argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2673"/> + <source>Invalid --clipboard-mode argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2693"/> + <source>Invalid --clipboard-file-transfers argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2718"/> + <source>Invalid --draganddrop argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2772"/> + <source>Invalid --vrdeproperty argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2780"/> + <source>Error: Failed to allocate memory for VRDE property '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2842"/> + <source>Invalid --vrdeauthtype argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="2960"/> + <source>Invalid --usbrename parameters, nothing renamed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3164"/> + <source>*** I/O APIC must be enabled for ICH9, enabling. *** +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3170"/> + <source>Invalid --chipset argument '%s' (valid: piix3,ich9)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3188"/> + <source>Invalid --iommu argument '%s' (valid: none,amd,automatic)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3197"/> + <source>Warning: On Intel hosts, 'automatic' will not enable an IOMMU since the Intel IOMMU device is not supported yet. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3202"/> + <source>Invalid --iommu argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3227"/> + <source>Invalid --tpm-type argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3284"/> + <source>Invalid list of screens specified +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3306"/> + <source>Cannot convert filename "%s" to absolute path +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3336"/> + <location filename="../VBoxManageModifyVM.cpp" line="3345"/> + <source>Error parsing video resolution '%s' (expected <width>x<height>)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3420"/> + <source>Invalid --autostop-type argument '%s' (valid: disabled, savestate, poweroff, acpishutdown)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3440"/> + <source>Invalid --pciattach argument '%s' (valid: 'HB:HD.HF@GB:GD.GF' or just 'HB:HD.HF')</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3458"/> + <source>Invalid --pcidetach argument '%s' (valid: 'HB:HD.HF')</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3492"/> + <source>Invalid --vm-process-priority '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyVM.cpp" line="3521"/> + <source>--testing-cfg-dword index %u is out of range: 0 thru 9</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Nat</name> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="96"/> + <source>Name: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="110"/> + <source>Network: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="113"/> + <source>Gateway: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="106"/> + <location filename="../VBoxManageNATNetwork.cpp" line="116"/> + <location filename="../VBoxManageNATNetwork.cpp" line="119"/> + <location filename="../VBoxManageNATNetwork.cpp" line="125"/> + <source>Yes</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="106"/> + <location filename="../VBoxManageNATNetwork.cpp" line="116"/> + <location filename="../VBoxManageNATNetwork.cpp" line="119"/> + <location filename="../VBoxManageNATNetwork.cpp" line="125"/> + <source>No</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="122"/> + <source>IPv6 Prefix: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="125"/> + <source>IPv6 Default: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="106"/> + <source>Enabled: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="116"/> + <source>DHCP Server: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="142"/> + <source>Port-forwarding (ipv4) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="146"/> + <source>Port-forwarding (ipv6) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="150"/> + <source>loopback mappings (ipv4) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="166"/> + <source>NAT Networks: + +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="198"/> + <source>%zu %s found +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="198"/> + <source>network</source> + <translation type="unfinished"></translation> + </message> + <message numerus="yes"> + <location filename="../VBoxManageNATNetwork.cpp" line="198"/> + <source>networks</source> + <translation type="unfinished"> + <numerusform></numerusform> + </translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="206"/> + <location filename="../VBoxManageNATNetwork.cpp" line="602"/> + <source>Not enough parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="261"/> + <source>You can only specify --netname only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="267"/> + <source>You can only specify --network only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="273"/> + <location filename="../VBoxManageNATNetwork.cpp" line="279"/> + <source>You can specify either --enable or --disable once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="285"/> + <source>You can specify --dhcp only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="291"/> + <source>You can specify --ipv6 only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="297"/> + <source>You can specify --ipv6-prefix only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="303"/> + <source>You can specify --ipv6-default only once.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="313"/> + <source>loopback couldn't be deleted on modified +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="324"/> + <location filename="../VBoxManageNATNetwork.cpp" line="362"/> + <source>Not enough parŠ°meters +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="349"/> + <source>Invalid port-forward rule %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="357"/> + <source>Port-forward could be deleted on modify +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="365"/> + <source>Port-forward rule name is too long +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="382"/> + <source>You need to specify the --netname option</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="388"/> + <source>You need to specify the --network option</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="396"/> + <source>Unknown operation (:%d)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="408"/> + <source>NATNetwork server already exists</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="412"/> + <source>Failed to create the NAT network service</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="415"/> + <source>NATNetwork server does not exist</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="426"/> + <location filename="../VBoxManageNATNetwork.cpp" line="432"/> + <location filename="../VBoxManageNATNetwork.cpp" line="444"/> + <location filename="../VBoxManageNATNetwork.cpp" line="451"/> + <location filename="../VBoxManageNATNetwork.cpp" line="462"/> + <location filename="../VBoxManageNATNetwork.cpp" line="470"/> + <location filename="../VBoxManageNATNetwork.cpp" line="565"/> + <source>Failed to set configuration</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="481"/> + <source>Failed to delete pf</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="506"/> + <source>Failed to add pf</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="532"/> + <location filename="../VBoxManageNATNetwork.cpp" line="538"/> + <source>invalid loopback string</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="573"/> + <source>Failed to remove nat network</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="580"/> + <source>Failed to start network</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="587"/> + <source>Failed to stop network</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageNATNetwork.cpp" line="636"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Nvram</name> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="121"/> + <source>No platform key file path was given to "enrollpk"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="123"/> + <source>No owner UUID was given to "enrollpk"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="147"/> + <source>Cannot read contents of file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="150"/> + <source>File "%s" is bigger than 32KByte</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="153"/> + <source>Cannot get size of file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="158"/> + <source>Cannot open file "%s": %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="250"/> + <source>No variable name was given to "queryvar"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="277"/> + <source>Error writing to '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="282"/> + <location filename="../VBoxManageModifyNvram.cpp" line="411"/> + <source>Error opening '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="329"/> + <source>No variable name was given to "deletevar"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="331"/> + <source>No owner UUID was given to "deletevar"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="381"/> + <source>No variable name was given to "changevar"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="383"/> + <source>No variable data filename was given to "changevar"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageModifyNvram.cpp" line="407"/> + <source>Error reading from '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Snapshot</name> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="198"/> + <location filename="../VBoxManageSnapshot.cpp" line="520"/> + <location filename="../VBoxManageSnapshot.cpp" line="594"/> + <source>This machine does not have any snapshots +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="254"/> + <source>[%RI32] Images and snapshots for medium "%ls" +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="329"/> + <source>Not enough parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="359"/> + <location filename="../VBoxManageSnapshot.cpp" line="561"/> + <source>Missing snapshot name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="404"/> + <source>Invalid unique name description '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="467"/> + <source>Failed to generate a unique snapshot name</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="483"/> + <source>Snapshot taken. UUID: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="485"/> + <source>Failed to take snapshot</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="500"/> + <source>Too many arguments</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="508"/> + <location filename="../VBoxManageSnapshot.cpp" line="628"/> + <source>Expecting snapshot name only</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="539"/> + <source>%s snapshot '%ls' (%ls) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="540"/> + <source>Deleting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="540"/> + <source>Restoring</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="554"/> + <source>Snapshot operation failed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageSnapshot.cpp" line="652"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Storage</name> + <message> + <location filename="../VBoxManageStorageController.cpp" line="166"/> + <location filename="../VBoxManageStorageController.cpp" line="1180"/> + <source>Invalid --type argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="305"/> + <source>Invalid medium type '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="327"/> + <source>Storage controller name not specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="347"/> + <source>Drive passthrough state cannot be changed while the VM is running +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="349"/> + <source>Bandwidth group cannot be changed while the VM is running +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="356"/> + <source>Could not find a controller named '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="370"/> + <source>Port not specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="377"/> + <source>Device not specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="441"/> + <source>No DVD/Floppy Drive attached to the controller '%s'at the port: %u, device: %u</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="461"/> + <source>The attachment is not supported by the storage controller '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="516"/> + <source>Cannot find the Guest Additions ISO image +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="542"/> + <source>Argument --type must be specified +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="556"/> + <source>The given attachment is not supported by the storage controller '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="578"/> + <location filename="../VBoxManageStorageController.cpp" line="582"/> + <source>Invalid host DVD drive name "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="591"/> + <source>Invalid host floppy drive name "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="598"/> + <source>Parameters --server and --target are required for iSCSI media</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="665"/> + <source>iSCSI disk created. UUID: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="676"/> + <source>Missing --medium argument</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="685"/> + <source>Invalid UUID or filename "%s"</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="695"/> + <source>Failed to set the medium/parent medium UUID</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="709"/> + <source>Failed to set the medium type</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="804"/> + <source>Invalid --passthrough argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="807"/> + <location filename="../VBoxManageStorageController.cpp" line="833"/> + <location filename="../VBoxManageStorageController.cpp" line="859"/> + <location filename="../VBoxManageStorageController.cpp" line="885"/> + <location filename="../VBoxManageStorageController.cpp" line="911"/> + <source>Couldn't find the controller attachment for the controller '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="830"/> + <source>Invalid --tempeject argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="856"/> + <source>Invalid --nonrotational argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="882"/> + <source>Invalid --discard argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="908"/> + <source>Invalid --hotpluggable argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="990"/> + <source>Too few parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1056"/> + <source>Storage controller name not specified +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1119"/> + <source>Invalid --add argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1186"/> + <location filename="../VBoxManageStorageController.cpp" line="1205"/> + <location filename="../VBoxManageStorageController.cpp" line="1236"/> + <location filename="../VBoxManageStorageController.cpp" line="1262"/> + <location filename="../VBoxManageStorageController.cpp" line="1281"/> + <source>Couldn't find the controller with the name: '%s' +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1230"/> + <source>Invalid --hostiocache argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageStorageController.cpp" line="1256"/> + <source>Invalid --bootable argument '%s'</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>UpdateCheck</name> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="81"/> + <source>Enabled: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="82"/> + <source>yes</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="82"/> + <source>no</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="89"/> + <source>Count: %u +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="99"/> + <source>Frequency: never +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="101"/> + <source>Frequency: every day +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="103"/> + <source>Frequency: every %u days +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="112"/> + <source>Stable - new minor and maintenance releases</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="116"/> + <source>All releases - new minor, maintenance, and major releases</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="120"/> + <source>With Betas - new minor, maintenance, major, and beta releases</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="125"/> + <source>Unset</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="132"/> + <source>Channel: %s +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="189"/> + <source>Unknown channel specified: '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="258"/> + <source>Checking for a new %ls version... +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="269"/> + <source>Failed to create update progress object: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="277"/> + <source>Checking for update failed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="296"/> + <source>A new version of %ls has been released! Version %ls is available at virtualbox.org. +You can download this version here: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="312"/> + <source>You are already running the most recent version of %ls. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="324"/> + <source>Something went wrong while checking for updates! +Please check network connection and try again later. +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="140"/> + <source>Last Check Date: %ls +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="195"/> + <source>The update frequency cannot be zero</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUpdateCheck.cpp" line="206"/> + <source>No change requested</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Usb</name> + <message> + <location filename="../VBoxManageUSB.cpp" line="178"/> + <location filename="../VBoxManageUSB.cpp" line="214"/> + <location filename="../VBoxManageUSB.cpp" line="216"/> + <location filename="../VBoxManageUSB.cpp" line="373"/> + <location filename="../VBoxManageUSB.cpp" line="571"/> + <source>Not enough parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="199"/> + <source>Invalid parameter '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="203"/> + <source>Invalid index '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="231"/> + <location filename="../VBoxManageUSB.cpp" line="246"/> + <location filename="../VBoxManageUSB.cpp" line="254"/> + <location filename="../VBoxManageUSB.cpp" line="267"/> + <location filename="../VBoxManageUSB.cpp" line="275"/> + <location filename="../VBoxManageUSB.cpp" line="283"/> + <location filename="../VBoxManageUSB.cpp" line="291"/> + <location filename="../VBoxManageUSB.cpp" line="299"/> + <location filename="../VBoxManageUSB.cpp" line="307"/> + <location filename="../VBoxManageUSB.cpp" line="315"/> + <location filename="../VBoxManageUSB.cpp" line="323"/> + <location filename="../VBoxManageUSB.cpp" line="336"/> + <location filename="../VBoxManageUSB.cpp" line="381"/> + <source>Missing argument to '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="261"/> + <source>Invalid --active argument '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="328"/> + <source>Failed to convert the --maskedinterfaces value '%s' to a number, vrc=%Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="343"/> + <source>Invalid USB filter action '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="346"/> + <source>Unknown option '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="363"/> + <location filename="../VBoxManageUSB.cpp" line="395"/> + <source>Mandatory options not supplied</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="581"/> + <source>Invalid number of parameters</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUSB.cpp" line="596"/> + <source>Parameter "%s" is invalid</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>Utils</name> + <message> + <location filename="../VBoxManageUtils.cpp" line="102"/> + <source>type bridged</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="106"/> + <source>type host-only</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="111"/> + <source>unknown type %RU32</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="116"/> + <source>Interface "%s" is of %s</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManageUtils.cpp" line="120"/> + <source>Interface "%s" doesn't seem to exist</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>VBoxManage</name> + <message> + <location filename="../VBoxManage.cpp" line="327"/> + <location filename="../VBoxManage.cpp" line="495"/> + <source>Progress object failure: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="344"/> + <source>Failed to get progress description: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="411"/> + <source>(%u/%u) %ls %02u%% => %02u%% (%d s remaining) +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="481"/> + <source>CANCELED +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="485"/> + <source>Progress state: %Rhrc +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="672"/> + <source>Password expected</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="680"/> + <source>No password file specified</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="687"/> + <source>Only one response file allowed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="695"/> + <source>Error reading response file '%s': %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="700"/> + <source>Invalid response file ('%s') encoding: %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="708"/> + <source>Failed to parse response file '%s' (bourne shell style): %Rrc</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="714"/> + <source>out of memory</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="755"/> + <source>commands: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="762"/> + <source>Invalid command '%s'</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="781"/> + <source>Failed to initialize COM because the global settings directory '%s' is not accessible!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="784"/> + <source>Failed to initialize COM! (hrc=%Rhrc)</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="867"/> + <source>Failed to create a session object!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="877"/> + <source>Failed to create the VirtualBox object!</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../VBoxManage.cpp" line="881"/> + <source>Most likely, the VirtualBox COM server is not running or failed to start.</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> |