VBoxServiceToolBox.cpp revision ad65c02966453e954ae479971daf0dedaae96fda
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * VBoxServiceToolbox - Internal (BusyBox-like) toolbox.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Copyright (C) 2012 Oracle Corporation
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * available from http://www.virtualbox.org. This file is free software;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * you can redistribute it and/or modify it under the terms of the GNU
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * General Public License (GPL) as published by the Free Software
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/*******************************************************************************
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync* Header Files *
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync*******************************************************************************/
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/*******************************************************************************
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync* Defined Constants And Macros *
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync*******************************************************************************/
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/** Generic option indices for commands. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/** Options indices for "vbox_cat". */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/** Flags for "vbox_ls". */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/** Flags for fs object output. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/*******************************************************************************
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync* Structures and Typedefs *
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync*******************************************************************************/
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync/** Pointer to a handler function. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * An file/directory entry. Used to cache
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * file names/paths for later processing.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** Our node. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** Name of the entry. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync} VBOXSERVICETOOLBOXPATHENTRY, *PVBOXSERVICETOOLBOXPATHENTRY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** Our node. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** The actual entry. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync} VBOXSERVICETOOLBOXDIRENTRY, *PVBOXSERVICETOOLBOXDIRENTRY;
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Displays a common header for all help text to stdout.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync "All rights reserved.\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Displays a help text to stdout.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTPrintf(" VBoxService [--use-toolbox] vbox_<command> [<general options>] <parameters>\n\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync "General options:\n\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " --machinereadable produce all output in machine-readable form\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " -V print version number and exit\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync "Commands:\n\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " cat [<general options>] <file>...\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " ls [<general options>] [--dereference|-L] [-l] [-R]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " [--verbose|-v] [<file>...]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " rm [<general options>] [-r|-R] <file>...\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " mktemp [<general options>] [--directory|-d] [--mode|-m <mode>]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " [--secure|-s] [--tmpdir|-t <path>]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " <template>\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " mkdir [<general options>] [--mode|-m <mode>] [--parents|-p]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " [--verbose|-v] <directory>...\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " stat [<general options>] [--file-system|-f]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " [--dereference|-L] [--terse|-t]\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync " [--verbose|-v] <file>...\n"
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Displays the program's version number.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Initializes the parseable stream(s).
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @return IPRT status code.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /* Set stdout's mode to binary. This is required for outputting all the machine-readable
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * data correctly. */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync int rc = RTStrmSetMode(g_pStdOut, 1 /* Binary mode */, -1 /* Current code set, not changed */);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTMsgError("Unable to set stdout to binary mode, rc=%Rrc\n", rc);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Prints a parseable stream header which contains the actual tool
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * which was called/used along with its stream version.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param pszToolName Name of the tool being used, e.g. "vbt_ls".
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param uVersion Stream version name. Handy for distinguishing
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * different stream versions later.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic void VBoxServiceToolboxPrintStrmHeader(const char *pszToolName, uint32_t uVersion)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTPrintf("hdr_id=%s%chdr_ver=%u%c", pszToolName, 0, uVersion, 0);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Prints a standardized termination sequence indicating that the
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * parseable stream just ended.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic void VBoxServiceToolboxPrintStrmTermination()
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Parse a file mode string from the command line (currently octal only)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * and print an error message and return an error if necessary.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic int vboxServiceToolboxParseMode(const char *pcszMode, RTFMODE *pfMode)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync int rc = RTStrToUInt32Ex(pcszMode, NULL, 8 /* Base */, pfMode);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync if (RT_FAILURE(rc)) /* Only octet based values supported right now! */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync RTMsgError("Mode flag strings not implemented yet! Use octal numbers instead. (%s)\n",
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Destroys a path buffer list.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @return IPRT status code.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param pList Pointer to list to destroy.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic void VBoxServiceToolboxPathBufDestroy(PRTLISTNODE pList)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync /** @todo use RTListForEachSafe */
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXSERVICETOOLBOXPATHENTRY pNode = RTListGetFirst(pList, VBOXSERVICETOOLBOXPATHENTRY, Node);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXSERVICETOOLBOXPATHENTRY pNext = RTListNodeIsLast(pList, &pNode->Node)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync : RTListNodeGetNext(&pNode->Node, VBOXSERVICETOOLBOXPATHENTRY, Node);
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * Adds a path entry (file/directory/whatever) to a given path buffer list.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @return IPRT status code.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param pList Pointer to list to add entry to.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync * @param pszName Name of entry to add.
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsyncstatic int VBoxServiceToolboxPathBufAddPathEntry(PRTLISTNODE pList, const char *pszName)
61cb83a8ccd1dd7f671f31fa93c9d8b7be09b4ccvboxsync PVBOXSERVICETOOLBOXPATHENTRY pNode = (PVBOXSERVICETOOLBOXPATHENTRY)RTMemAlloc(sizeof(VBOXSERVICETOOLBOXPATHENTRY));
return rc;
static char g_paszCatHelp[] =
int ch;
bool fUsageOK = true;
switch (ch)
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SUCCESS;
case VINF_GETOPT_NOT_OPTION:
if (pszOutput)
if (pMsg)
char chFileType;
szTimeBirth, 0,
szTimeChange, 0,
szTimeAccess, 0);
return VINF_SUCCESS;
return rc;
return rc;
PVBOXSERVICETOOLBOXDIRENTRY pNode = (PVBOXSERVICETOOLBOXDIRENTRY)RTMemAlloc(sizeof(VBOXSERVICETOOLBOXDIRENTRY));
if (pNode)
case RTFS_TYPE_SYMLINK:
case RTFS_TYPE_DIRECTORY:
return rc;
static char g_paszLsHelp[] =
int ch;
bool fVerbose = false;
switch (ch)
return RTEXITCODE_SUCCESS;
fVerbose = true;
return RTEXITCODE_SUCCESS;
case VINF_GETOPT_NOT_OPTION:
&objInfo);
else if (fVerbose)
static char g_paszRmHelp[] =
int *prc)
if (!fActive)
bool fVerbose = false;
int cNonOptions = 0;
switch (ch)
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SUCCESS;
case VINF_GETOPT_NOT_OPTION:
++cNonOptions;
return RTEXITCODE_FAILURE;
&rc);
static char g_paszMkTempHelp[] =
int *prc)
if (!fActive)
/* Isn't that a bit long? s/VBOXSERVICETOOLBOX/VSTB/ ? */
bool fVerbose = false;
int cNonOptions = 0;
bool fModeSet = false;
const char *pcszTemplate;
switch (ch)
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SYNTAX;
fModeSet = true;
#ifndef RT_OS_WINDOWS
case VINF_GETOPT_NOT_OPTION:
++cNonOptions;
return RTEXITCODE_SYNTAX;
return RTEXITCODE_SYNTAX;
toolboxMkTempReport("Template '%s' should contain a file name with no path and at least one 'X' character.\n",
return RTEXITCODE_FAILURE;
return RTEXITCODE_FAILURE;
if (pcszPath)
pcszPath);
return RTEXITCODE_FAILURE;
return RTEXITCODE_FAILURE;
return RTEXITCODE_FAILURE;
toolboxMkTempReport("The following error occurred while creating a temporary directory from template '%s': %Rrc.\n",
NULL);
toolboxMkTempReport("The following error occurred while creating a temporary file from template '%s': %Rrc.\n",
NULL);
static char g_paszMkDirHelp[] =
int ch;
bool fMakeParentDirs = false;
bool fVerbose = false;
int cDirsCreated = 0;
switch (ch)
fMakeParentDirs = true;
return RTEXITCODE_SYNTAX;
#ifndef RT_OS_WINDOWS
fVerbose = true;
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SUCCESS;
case VINF_GETOPT_NOT_OPTION:
if (fMakeParentDirs)
if (fVerbose)
cDirsCreated++;
if (cDirsCreated == 0)
return RTEXITCODE_SUCCESS;
static char g_paszStatHelp[] =
int ch;
bool fVerbose = false;
switch (ch)
fVerbose = true;
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SUCCESS;
case VINF_GETOPT_NOT_OPTION:
&objInfo);
else if (fVerbose)
const char *pszName;
const s_aTools[] =
return NULL;
if (!pfnHandler)
if (!pfnHandler)