Changeset 37921 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Jul 13, 2011 2:42:21 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
r37860 r37921 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxServiceTool Box - Internal (BusyBox-like) toolbox.3 * VBoxServiceToolbox - Internal (BusyBox-like) toolbox. 4 4 */ 5 5 … … 35 35 36 36 #ifndef RT_OS_WINDOWS 37 # include <sys/stat.h>37 # include <sys/stat.h> /* need umask */ 38 38 #endif 39 39 … … 44 44 45 45 46 /******************************************************************************* 47 * Defined Constants And Macros * 48 *******************************************************************************/ 46 49 /** Options indices for "vbox_cat". */ 47 50 #define CAT_OPT_NO_CONTENT_INDEXED 1000 … … 56 59 VBOXSERVICETOOLBOXLSFLAG_RECURSIVE = 0x1, 57 60 VBOXSERVICETOOLBOXLSFLAG_SYMLINKS = 0x2 58 } VBOXSERVICETOOLBOXLSFLAG , *PVBOXSERVICETOOLBOXLSFLAG;61 } VBOXSERVICETOOLBOXLSFLAG; 59 62 60 63 /** Flags for fs object output. */ … … 64 67 VBOXSERVICETOOLBOXOUTPUTFLAG_LONG = 0x1, 65 68 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 *******************************************************************************/ 74 75 /** 75 76 * An file/directory entry. Used to cache … … 302 303 RTGetOptInit(&GetState, argc, argv, 303 304 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*/); 311 306 312 307 int rc = VINF_SUCCESS; … … 451 446 452 447 RTFMODE fMode = pObjInfo->Attr.fMode; 453 char c FileType;448 char chFileType; 454 449 switch (fMode & RTFS_TYPE_MASK) 455 450 { 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; 467 460 } 468 461 /** @todo sticy bits++ */ … … 474 467 /** @todo Skip node_id if not present/available! */ 475 468 RTPrintf("ftype=%c%cnode_id=%RU64%cname_len=%RU16%cname=%s%c", 476 c FileType, 0, (uint64_t)pObjInfo->Attr.u.Unix.INodeId, 0,469 chFileType, 0, (uint64_t)pObjInfo->Attr.u.Unix.INodeId, 0, 477 470 cbName, 0, pszName, 0); 478 471 } 479 472 else 480 RTPrintf("%c %#18llx %3d %s\n", (uint64_t)pObjInfo->Attr.u.Unix.INodeId,481 c FileType, cbName, pszName);473 RTPrintf("%c %#18llx %3d %s\n", 474 chFileType, (uint64_t)pObjInfo->Attr.u.Unix.INodeId, cbName, pszName); 482 475 483 476 if (uOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE) /* End of data block. */ … … 488 481 if (uOutputFlags & VBOXSERVICETOOLBOXOUTPUTFLAG_PARSEABLE) 489 482 { 490 RTPrintf("ftype=%c%c", c FileType, 0);483 RTPrintf("ftype=%c%c", chFileType, 0); 491 484 RTPrintf("owner_mask=%c%c%c%c", 492 485 fMode & RTFS_UNIX_IRUSR ? 'r' : '-', … … 545 538 else 546 539 { 547 RTPrintf("%c", c FileType);540 RTPrintf("%c", chFileType); 548 541 RTPrintf("%c%c%c", 549 542 fMode & RTFS_UNIX_IRUSR ? 'r' : '-', … … 750 743 RTGetOptInit(&GetState, argc, argv, 751 744 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); 759 746 760 747 int rc = VINF_SUCCESS; … … 802 789 803 790 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; 814 802 815 803 default: … … 842 830 RTListForEach(&fileList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node) 843 831 { 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 844 845 if (RTFileExists(pNodeIt->pszName)) 845 846 { … … 904 905 RTGetOptInit(&GetState, argc, argv, 905 906 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); 913 908 914 909 int rc = VINF_SUCCESS; … … 955 950 956 951 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 967 961 968 962 default: … … 985 979 RTListForEach(&dirList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node) 986 980 { 987 rc = fMakeParentDirs ?988 989 981 rc = fMakeParentDirs 982 ? RTDirCreateFullPath(pNodeIt->pszName, dirMode) 983 : RTDirCreate(pNodeIt->pszName, dirMode); 990 984 991 985 if (RT_SUCCESS(rc) && fVerbose) … … 993 987 else if (RT_FAILURE(rc)) /** @todo Add a switch with more helpful error texts! */ 994 988 { 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); 1001 990 break; 1002 991 } … … 1034 1023 RTGetOptInit(&GetState, argc, argv, 1035 1024 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); 1043 1026 1044 1027 int rc = VINF_SUCCESS; … … 1104 1087 RTListForEach(&fileList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node) 1105 1088 { 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'. */ 1106 1094 /* Only check for file existence for now. */ 1107 1095 RTFSOBJINFO objInfo; … … 1183 1171 bool VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit) 1184 1172 { 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); 1195 1203 return true; 1196 1204 } 1197 1205 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 1219 1224 return false; 1220 1225 }
Note:
See TracChangeset
for help on using the changeset viewer.