VirtualBox

Changeset 37921 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Jul 13, 2011 2:42:21 PM (14 years ago)
Author:
vboxsync
Message:

VBoxServiceToolbox.cpp: Fixed the symlink invocation (must strip filename) and added a toolbox invocation mode for debugging (VBoxService --use-toolbox <command> [arguments]). Made 'ls' not try print the INODE number as char. Added a TODO to both ls and stat regarding RTFileOpen/RTDirOpen+Query where RTPathQueryEx should be used.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp

    r37860 r37921  
    11/* $Id$ */
    22/** @file
    3  * VBoxServiceToolBox - Internal (BusyBox-like) toolbox.
     3 * VBoxServiceToolbox - Internal (BusyBox-like) toolbox.
    44 */
    55
     
    3535
    3636#ifndef RT_OS_WINDOWS
    37 #include <sys/stat.h>
     37# include <sys/stat.h> /* need umask */
    3838#endif
    3939
     
    4444
    4545
     46/*******************************************************************************
     47*   Defined Constants And Macros                                               *
     48*******************************************************************************/
    4649/** Options indices for "vbox_cat". */
    4750#define CAT_OPT_NO_CONTENT_INDEXED              1000
     
    5659    VBOXSERVICETOOLBOXLSFLAG_RECURSIVE =        0x1,
    5760    VBOXSERVICETOOLBOXLSFLAG_SYMLINKS =         0x2
    58 } VBOXSERVICETOOLBOXLSFLAG, *PVBOXSERVICETOOLBOXLSFLAG;
     61} VBOXSERVICETOOLBOXLSFLAG;
    5962
    6063/** Flags for fs object output. */
     
    6467    VBOXSERVICETOOLBOXOUTPUTFLAG_LONG =         0x1,
    6568    VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE =    0x2
    66 } VBOXSERVICETOOLBOXOUTPUTFLAG, *PVBOXSERVICETOOLBOXOUTPUTFLAG;
    67 
    68 /* Enable the following define to be able to debug/invoke the toolbox
    69  * commandos directly from command line, e.g. VBoxService vbox_cat [args] */
    70 #ifdef DEBUG
    71 //# define VBOXSERVICE_TOOLBOX_DEBUG
    72 #endif
    73 
     69} VBOXSERVICETOOLBOXOUTPUTFLAG;
     70
     71
     72/*******************************************************************************
     73*   Structures and Typedefs                                                    *
     74*******************************************************************************/
    7475/**
    7576 * An file/directory entry. Used to cache
     
    302303    RTGetOptInit(&GetState, argc, argv,
    303304                 s_aOptions, RT_ELEMENTS(s_aOptions),
    304                  /* Index of argv to start with. */
    305 #ifdef VBOXSERVICE_TOOLBOX_DEBUG
    306                  2,
    307 #else
    308                  1,
    309 #endif
    310                  0);
     305                 1 /*iFirst*/, 0 /*fFlags*/);
    311306
    312307    int rc = VINF_SUCCESS;
     
    451446
    452447    RTFMODE fMode = pObjInfo->Attr.fMode;
    453     char cFileType;
     448    char chFileType;
    454449    switch (fMode & RTFS_TYPE_MASK)
    455450    {
    456         case RTFS_TYPE_FIFO:        cFileType = 'f'; break;
    457         case RTFS_TYPE_DEV_CHAR:    cFileType = 'c'; break;
    458         case RTFS_TYPE_DIRECTORY:   cFileType = 'd'; break;
    459         case RTFS_TYPE_DEV_BLOCK:   cFileType = 'b'; break;
    460         case RTFS_TYPE_FILE:        cFileType = '-'; break;
    461         case RTFS_TYPE_SYMLINK:     cFileType = 'l'; break;
    462         case RTFS_TYPE_SOCKET:      cFileType = 's'; break;
    463         case RTFS_TYPE_WHITEOUT:    cFileType = 'w'; break;
    464         default:
    465             cFileType = '?';
    466             break;
     451        case RTFS_TYPE_FIFO:        chFileType = 'f'; break;
     452        case RTFS_TYPE_DEV_CHAR:    chFileType = 'c'; break;
     453        case RTFS_TYPE_DIRECTORY:   chFileType = 'd'; break;
     454        case RTFS_TYPE_DEV_BLOCK:   chFileType = 'b'; break;
     455        case RTFS_TYPE_FILE:        chFileType = '-'; break;
     456        case RTFS_TYPE_SYMLINK:     chFileType = 'l'; break;
     457        case RTFS_TYPE_SOCKET:      chFileType = 's'; break;
     458        case RTFS_TYPE_WHITEOUT:    chFileType = 'w'; break;
     459        default:                    chFileType = '?'; break;
    467460    }
    468461    /** @todo sticy bits++ */
     
    474467            /** @todo Skip node_id if not present/available! */
    475468            RTPrintf("ftype=%c%cnode_id=%RU64%cname_len=%RU16%cname=%s%c",
    476                      cFileType, 0, (uint64_t)pObjInfo->Attr.u.Unix.INodeId, 0,
     469                     chFileType, 0, (uint64_t)pObjInfo->Attr.u.Unix.INodeId, 0,
    477470                     cbName, 0, pszName, 0);
    478471        }
    479472        else
    480             RTPrintf("%c %#18llx %3d %s\n", (uint64_t)pObjInfo->Attr.u.Unix.INodeId,
    481                      cFileType, cbName, pszName);
     473            RTPrintf("%c %#18llx %3d %s\n",
     474                     chFileType, (uint64_t)pObjInfo->Attr.u.Unix.INodeId, cbName, pszName);
    482475
    483476        if (uOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE) /* End of data block. */
     
    488481        if (uOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE)
    489482        {
    490             RTPrintf("ftype=%c%c", cFileType, 0);
     483            RTPrintf("ftype=%c%c", chFileType, 0);
    491484            RTPrintf("owner_mask=%c%c%c%c",
    492485                     fMode & RTFS_UNIX_IRUSR ? 'r' : '-',
     
    545538        else
    546539        {
    547             RTPrintf("%c", cFileType);
     540            RTPrintf("%c", chFileType);
    548541            RTPrintf("%c%c%c",
    549542                     fMode & RTFS_UNIX_IRUSR ? 'r' : '-',
     
    750743    RTGetOptInit(&GetState, argc, argv,
    751744                 s_aOptions, RT_ELEMENTS(s_aOptions),
    752                  /* Index of argv to start with. */
    753 #ifdef VBOXSERVICE_TOOLBOX_DEBUG
    754                  2,
    755 #else
    756                  1,
    757 #endif
    758                  RTGETOPTINIT_FLAGS_OPTS_FIRST);
     745                 1 /*iFirst*/, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    759746
    760747    int rc = VINF_SUCCESS;
     
    802789
    803790            case VINF_GETOPT_NOT_OPTION:
    804                 {
    805                     /* Add file(s) to buffer. This enables processing multiple files
    806                      * at once.
    807                      *
    808                      * Since the non-options (RTGETOPTINIT_FLAGS_OPTS_FIRST) come last when
    809                      * processing this loop it's safe to immediately exit on syntax errors
    810                      * or showing the help text (see above). */
    811                     rc = VBoxServiceToolboxPathBufAddPathEntry(&fileList, ValueUnion.psz);
    812                     break;
    813                 }
     791                /* Add file(s) to buffer. This enables processing multiple files
     792                 * at once.
     793                 *
     794                 * Since the non-options (RTGETOPTINIT_FLAGS_OPTS_FIRST) come last when
     795                 * processing this loop it's safe to immediately exit on syntax errors
     796                 * or showing the help text (see above). */
     797                rc = VBoxServiceToolboxPathBufAddPathEntry(&fileList, ValueUnion.psz);
     798                /** @todo r=bird: Nit: creating a list here is not really
     799                 *        necessary since you've got one in argv that's
     800                 *        accessible via RTGetOpt. */
     801                break;
    814802
    815803            default:
     
    842830        RTListForEach(&fileList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node)
    843831        {
     832            /** @todo r=bird: Call RTPathQueryInfoEx directly (RTFileExists
     833             *        does it under the hood) and skip the RTFileOpen stuff!
     834             *        /bin/ls can list full details for files you cannot open.
     835             *
     836             * Just try the following:
     837             * @code
     838                      $ echo > testfile
     839                      $ chmod 600 testfile
     840                      $ sudo chown root:root testfile
     841                      $ ls -la testfile
     842             * @endcode
     843             */
     844
    844845            if (RTFileExists(pNodeIt->pszName))
    845846            {
     
    904905    RTGetOptInit(&GetState, argc, argv,
    905906                 s_aOptions, RT_ELEMENTS(s_aOptions),
    906                  /* Index of argv to start with. */
    907 #ifdef VBOXSERVICE_TOOLBOX_DEBUG
    908                  2,
    909 #else
    910                  1,
    911 #endif
    912                  RTGETOPTINIT_FLAGS_OPTS_FIRST);
     907                 1 /*iFirst*/, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    913908
    914909    int rc = VINF_SUCCESS;
     
    955950
    956951            case VINF_GETOPT_NOT_OPTION:
    957                 {
    958                     /* Add path(s) to buffer. This enables processing multiple paths
    959                      * at once.
    960                      *
    961                      * Since the non-options (RTGETOPTINIT_FLAGS_OPTS_FIRST) come last when
    962                      * processing this loop it's safe to immediately exit on syntax errors
    963                      * or showing the help text (see above). */
    964                     rc = VBoxServiceToolboxPathBufAddPathEntry(&dirList, ValueUnion.psz);
    965                     break;
    966                 }
     952               /* Add path(s) to buffer. This enables processing multiple paths
     953                * at once.
     954                *
     955                * Since the non-options (RTGETOPTINIT_FLAGS_OPTS_FIRST) come last when
     956                * processing this loop it's safe to immediately exit on syntax errors
     957                * or showing the help text (see above). */
     958               rc = VBoxServiceToolboxPathBufAddPathEntry(&dirList, ValueUnion.psz);
     959               break;
     960
    967961
    968962            default:
     
    985979        RTListForEach(&dirList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node)
    986980        {
    987             rc = fMakeParentDirs ?
    988                  RTDirCreateFullPath(pNodeIt->pszName, dirMode)
    989                  : RTDirCreate(pNodeIt->pszName, dirMode);
     981            rc = fMakeParentDirs
     982               ? RTDirCreateFullPath(pNodeIt->pszName, dirMode)
     983               : RTDirCreate(pNodeIt->pszName, dirMode);
    990984
    991985            if (RT_SUCCESS(rc) && fVerbose)
     
    993987            else if (RT_FAILURE(rc)) /** @todo Add a switch with more helpful error texts! */
    994988            {
    995                 PCRTSTATUSMSG pMsg = RTErrGet(rc);
    996                 if (pMsg)
    997                     RTMsgError("mkdir: Could not create directory '%s': %s\n",
    998                                pNodeIt->pszName, pMsg->pszMsgFull);
    999                 else
    1000                     RTMsgError("mkdir: Could not create directory '%s', rc=%Rrc\n", pNodeIt->pszName, rc);
     989                RTMsgError("mkdir: Could not create directory '%s': %Rra\n", pNodeIt->pszName, rc);
    1001990                break;
    1002991            }
     
    10341023    RTGetOptInit(&GetState, argc, argv,
    10351024                 s_aOptions, RT_ELEMENTS(s_aOptions),
    1036                  /* Index of argv to start with. */
    1037 #ifdef VBOXSERVICE_TOOLBOX_DEBUG
    1038                  2,
    1039 #else
    1040                  1,
    1041 #endif
    1042                  RTGETOPTINIT_FLAGS_OPTS_FIRST);
     1025                 1 /*iFirst*/, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    10431026
    10441027    int rc = VINF_SUCCESS;
     
    11041087        RTListForEach(&fileList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node)
    11051088        {
     1089            /** @todo r=bird: Use RTPathQueryInfoEx!  The tool is called
     1090             *        'stat' because it's just a wrapper for 'stat()',
     1091             *        right?  Our equvialent to the 'stat()' call is
     1092             *        RTPathQueryInfoEx().  Same permission issues as above
     1093             *        with 'ls'. */
    11061094            /* Only check for file existence for now. */
    11071095            RTFSOBJINFO objInfo;
     
    11831171bool VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit)
    11841172{
    1185     if (argc > 0) /* Do we have at least a main command? */
    1186     {
    1187         int iCmdIdx = 0;
    1188 #ifdef VBOXSERVICE_TOOLBOX_DEBUG
    1189         iCmdIdx = 1;
    1190 #endif
    1191         if (   !strcmp(argv[iCmdIdx], "cat")
    1192             || !strcmp(argv[iCmdIdx], "vbox_cat"))
    1193         {
    1194             *prcExit = VBoxServiceToolboxCat(argc, argv);
     1173    static struct
     1174    {
     1175        const char *pszName;
     1176        RTEXITCODE (*pfnHandler)(int argc, char **argv);
     1177    }
     1178    const s_aTools[] =
     1179    {
     1180        { "cat",    VBoxServiceToolboxCat   },
     1181        { "ls",     VBoxServiceToolboxLs    },
     1182        { "mkdir",  VBoxServiceToolboxMkDir },
     1183        { "stat",   VBoxServiceToolboxStat  },
     1184    };
     1185
     1186    /*
     1187     * Check if the file named in argv[0] is one of the toolbox programs.
     1188     */
     1189    AssertReturn(argc > 0, false);
     1190    const char *pszTool = RTPathFilename(argv[0]);
     1191    /* Skip optional 'vbox_' prefix. */
     1192    if (   pszTool[0] == 'v'
     1193        && pszTool[1] == 'b'
     1194        && pszTool[2] == 'o'
     1195        && pszTool[3] == 'x'
     1196        && pszTool[4] == '_')
     1197        pszTool += 5;
     1198
     1199    for (unsigned i = 0; i < RT_ELEMENTS(s_aTools); i++)
     1200        if (!strcmp(s_aTools[i].pszName, pszTool))
     1201        {
     1202            *prcExit = s_aTools[i].pfnHandler(argc, argv);
    11951203            return true;
    11961204        }
    11971205
    1198         if (   !strcmp(argv[iCmdIdx], "ls")
    1199             || !strcmp(argv[iCmdIdx], "vbox_ls"))
    1200         {
    1201             *prcExit = VBoxServiceToolboxLs(argc, argv);
    1202             return true;
    1203         }
    1204 
    1205         if (   !strcmp(argv[iCmdIdx], "mkdir")
    1206             || !strcmp(argv[iCmdIdx], "vbox_mkdir"))
    1207         {
    1208             *prcExit = VBoxServiceToolboxMkDir(argc, argv);
    1209             return true;
    1210         }
    1211 
    1212         if (   !strcmp(argv[iCmdIdx], "stat")
    1213             || !strcmp(argv[iCmdIdx], "vbox_stat"))
    1214         {
    1215             *prcExit = VBoxServiceToolboxStat(argc, argv);
    1216             return true;
    1217         }
    1218     }
     1206    /*
     1207     * For debugging and testing purposes we also allow toolbox program access
     1208     * when the first VBoxService argument is --use-toolbox.
     1209     */
     1210    if (argc >= 3 && !strcmp(argv[1], "--use-toolbox"))
     1211    {
     1212        pszTool = argv[2];
     1213        for (unsigned i = 0; i < RT_ELEMENTS(s_aTools); i++)
     1214            if (!strcmp(s_aTools[i].pszName, pszTool))
     1215            {
     1216                *prcExit = s_aTools[i].pfnHandler(argc - 2, argv + 2);
     1217                return true;
     1218            }
     1219
     1220       *prcExit = RTMsgErrorExit(RTEXITCODE_SYNTAX, "Toolbox program '%s' does not exist", pszTool);
     1221       return true;
     1222    }
     1223
    12191224    return false;
    12201225}
Note: See TracChangeset for help on using the changeset viewer.

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