Changeset 34273 in vbox
- Timestamp:
- Nov 23, 2010 10:14:46 AM (14 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r33854 r34273 519 519 * mutex because VBoxService might spawn itself to execute some commands. 520 520 */ 521 rc = VBoxServiceToolboxMain(argc - 1, &argv[1]);522 if ( rc != VERR_NOT_FOUND) /* Internal tool found? Then bail out. */523 return rc;521 int iExitCode; 522 if (VBoxServiceToolboxMain(argc - 1, &argv[1], &iExitCode)) 523 return iExitCode; 524 524 } 525 525 #endif -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r33540 r34273 280 280 281 281 #ifdef VBOXSERVICE_TOOLBOX 282 extern int VBoxServiceToolboxMain(int argc, char **argv);282 extern bool VBoxServiceToolboxMain(int argc, char **argv, int *piExitCode); 283 283 #endif 284 284 285 285 #ifdef RT_OS_WINDOWS 286 286 # ifdef VBOX_WITH_GUEST_PROPS 287 extern int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList);288 extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID);287 extern int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList); 288 extern int VBoxServiceWinGetComponentVersions(uint32_t uiClientID); 289 289 # endif /* VBOX_WITH_GUEST_PROPS */ 290 290 #endif /* RT_OS_WINDOWS */ 291 291 292 292 #ifdef VBOX_WITH_GUEST_CONTROL 293 extern int VBoxServiceControlExecHandleCmdStartProcess(uint32_t u32ClientId, uint32_t uNumParms);294 extern int VBoxServiceControlExecHandleCmdSetInput(uint32_t u32ClientId, uint32_t uNumParms);295 extern int VBoxServiceControlExecHandleCmdGetOutput(uint32_t u32ClientId, uint32_t uNumParms);296 extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,297 const char *pszArgs, uint32_t uNumArgs,298 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,299 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);300 extern void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread);301 extern void VBoxServiceControlExecDeletePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf);302 extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,303 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);304 extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,305 uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten);293 extern int VBoxServiceControlExecHandleCmdStartProcess(uint32_t u32ClientId, uint32_t uNumParms); 294 extern int VBoxServiceControlExecHandleCmdSetInput(uint32_t u32ClientId, uint32_t uNumParms); 295 extern int VBoxServiceControlExecHandleCmdGetOutput(uint32_t u32ClientId, uint32_t uNumParms); 296 extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags, 297 const char *pszArgs, uint32_t uNumArgs, 298 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 299 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS); 300 extern void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread); 301 extern void VBoxServiceControlExecDeletePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf); 302 extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 303 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead); 304 extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 305 uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten); 306 306 #endif /* VBOX_WITH_GUEST_CONTROL */ 307 307 308 308 #ifdef VBOXSERVICE_MANAGEMENT 309 extern uint32_t VBoxServiceBalloonQueryPages(uint32_t cbPage);309 extern uint32_t VBoxServiceBalloonQueryPages(uint32_t cbPage); 310 310 #endif 311 311 #if defined(VBOX_WITH_PAGE_SHARING) && defined(RT_OS_WINDOWS) 312 extern RTEXITCODE VBoxServicePageSharingInitFork(void);312 extern RTEXITCODE VBoxServicePageSharingInitFork(void); 313 313 #endif 314 314 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
r34249 r34273 23 23 24 24 #include <iprt/assert.h> 25 #include <iprt/buildconfig.h> 25 26 #include <iprt/dir.h> 26 27 #include <iprt/file.h> … … 28 29 #include <iprt/list.h> 29 30 #include <iprt/mem.h> 31 #include <iprt/message.h> 30 32 #include <iprt/path.h> 31 33 #include <iprt/string.h> … … 37 39 38 40 #include <VBox/VBoxGuestLib.h> 41 #include <VBox/version.h> 39 42 #include "VBoxServiceInternal.h" 40 43 #include "VBoxServiceUtils.h" 41 44 42 /** @todo r=bird: Don't use VBoxServiceError here, just use RTMsg**. */ 43 /** @todo r=bird: 'static' is a wonderful keyword, please use it as much as 44 * possible like I've said in the coding guidelines. Not only does it 45 * help wrt to linking, but it also helps understanding what's 46 * internal and external interfaces in a source file! */ 45 46 #define CAT_OPT_NO_CONTENT_INDEXED 1000 47 48 /** 49 * An file/directory entry. Used to cache 50 * file names/paths for later processing. 51 */ 52 typedef struct VBOXSERVICETOOLBOXPATHENTRY 53 { 54 /** Our node. */ 55 RTLISTNODE Node; 56 /** Name of the entry. */ 57 char *pszName; 58 } VBOXSERVICETOOLBOXPATHENTRY, *PVBOXSERVICETOOLBOXPATHENTRY; 47 59 48 60 … … 50 62 * Displays a help text to stdout. 51 63 */ 52 void VBoxServiceToolboxShowUsage(void)64 static void VBoxServiceToolboxShowUsage(void) 53 65 { 54 66 RTPrintf("Toolbox Usage:\n" 55 67 "cat [FILE] - Concatenate FILE(s), or standard input, to standard output\n" 68 "\n" 69 "mkdir - Make directories\n" 56 70 "\n"); 57 71 } … … 59 73 60 74 /** 61 * 62 * 63 * @return int 64 * 75 * Displays the program's version number. 76 */ 77 static void VBoxServiceToolboxShowVersion(void) 78 { 79 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision()); 80 } 81 82 83 /** 84 * Displays an error message because of syntax error. 85 * 86 * @return VERR_INVALID_PARAMETER 65 87 * @param pszFormat 66 88 */ 67 int VBoxServiceToolboxErrorSyntax(const char *pszFormat, ...)89 static int VBoxServiceToolboxErrorSyntax(const char *pszFormat, ...) 68 90 { 69 91 va_list args; … … 73 95 "Syntax error: %N\n", pszFormat, &args); 74 96 va_end(args); 75 VBoxServiceToolboxShowUsage();76 97 return VERR_INVALID_PARAMETER; 77 98 } … … 79 100 80 101 /** 81 * 82 * 83 * @return int 84 * 85 * @param hInput 86 * @param hOutput 87 */ 88 int VBoxServiceToolboxCatOutput(RTFILE hInput, RTFILE hOutput) 102 * Destroys a path buffer list. 103 * 104 * @return IPRT status code. 105 * @param pList Pointer to list to destroy. 106 */ 107 static void VBoxServiceToolboxPathBufDestroy(PRTLISTNODE pList) 108 { 109 AssertPtr(pList); 110 PVBOXSERVICETOOLBOXPATHENTRY pNode = RTListNodeGetFirst(pList, VBOXSERVICETOOLBOXPATHENTRY, Node); 111 while (pNode) 112 { 113 PVBOXSERVICETOOLBOXPATHENTRY pNext = RTListNodeIsLast(pList, &pNode->Node) 114 ? NULL : 115 RTListNodeGetNext(&pNode->Node, 116 VBOXSERVICETOOLBOXPATHENTRY, Node); 117 RTListNodeRemove(&pNode->Node); 118 119 RTStrFree(pNode->pszName); 120 121 RTMemFree(pNode); 122 pNode = pNext; 123 } 124 } 125 126 127 /** 128 * Adds a path entry (file/directory/whatever) to a given path buffer list. 129 * 130 * @return IPRT status code. 131 * @param pList Pointer to list to add entry to. 132 * @param pszName Name of entry to add. 133 */ 134 static int VBoxServiceToolboxPathBufAddPathEntry(PRTLISTNODE pList, const char *pszName) 135 { 136 AssertPtrReturn(pList, VERR_INVALID_PARAMETER); 137 138 int rc = VINF_SUCCESS; 139 PVBOXSERVICETOOLBOXPATHENTRY pNode = (PVBOXSERVICETOOLBOXPATHENTRY)RTMemAlloc(sizeof(VBOXSERVICETOOLBOXPATHENTRY)); 140 if (pNode) 141 { 142 pNode->pszName = RTStrDup(pszName); 143 AssertPtr(pNode->pszName); 144 145 /*rc =*/ RTListAppend(pList, &pNode->Node); 146 } 147 else 148 rc = VERR_NO_MEMORY; 149 return rc; 150 } 151 152 153 /** 154 * Performs the actual output operation of "vbox_cat". 155 * 156 * @return IPRT status code. 157 * @param hInput Handle of input file (if any) to use; 158 * else stdin will be used. 159 * @param hOutput Handle of output file (if any) to use; 160 * else stdout will be used. 161 */ 162 static int VBoxServiceToolboxCatOutput(RTFILE hInput, RTFILE hOutput) 89 163 { 90 164 int rc = VINF_SUCCESS; … … 93 167 rc = RTFileFromNative(&hInput, RTFILE_NATIVE_STDIN); 94 168 if (RT_FAILURE(rc)) 95 VBoxServiceError("cat: Could not translate input file to native handle, rc=%Rrc\n", rc);169 RTMsgError("cat: Could not translate input file to native handle, rc=%Rrc\n", rc); 96 170 } 97 171 … … 100 174 rc = RTFileFromNative(&hOutput, RTFILE_NATIVE_STDOUT); 101 175 if (RT_FAILURE(rc)) 102 VBoxServiceError("cat: Could not translate output file to native handle, rc=%Rrc\n", rc);176 RTMsgError("cat: Could not translate output file to native handle, rc=%Rrc\n", rc); 103 177 } 104 178 … … 130 204 131 205 132 /** @todo r=bird: Again, function headers like this are uslesss and better left 133 * out. */ 134 /** 135 * 136 * 137 * @return int 138 * 139 * @param argc 140 * @param argv 141 */ 142 int VBoxServiceToolboxMkDir(int argc, char **argv) 206 /** 207 * Main function for tool "vbox_mkdir". 208 * 209 * @return RTEXITCODE. 210 * @param argc Number of arguments. 211 * @param argv Pointer to argument array. 212 */ 213 static int VBoxServiceToolboxMkDir(int argc, char **argv) 143 214 { 144 215 static const RTGETOPTDEF s_aOptions[] = … … 152 223 RTGETOPTUNION ValueUnion; 153 224 RTGETOPTSTATE GetState; 154 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0); 155 /** @todo r=bird: Pass RTGETOPTINIT_FLAGS_OPTS_FIRST, our mkdir shall be 156 * like the GNU one wrt to option (dash-something) and argument 157 * order (dirs). */ 225 RTGetOptInit(&GetState, argc, argv, 226 s_aOptions, RT_ELEMENTS(s_aOptions), 227 1 /* Index of argv to start with. */, RTGETOPTINIT_FLAGS_OPTS_FIRST); 158 228 159 229 int rc = VINF_SUCCESS; … … 161 231 bool fVerbose = false; 162 232 163 char szDir[RTPATH_MAX];164 233 RTFMODE newMode = 0; 165 #ifdef RT_OS_WINDOWS 166 RTFMODE fileMode = 0; 167 #else 168 RT FMODE fileMode = S_IRWXU | S_IRWXG | S_IRWXO; /** @todo r=bird: We've got RTFS_ defines for these, they are x-platform. Why 'file' when we're creating directories? */169 #endif 234 RTFMODE dirMode = RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG | RTFS_UNIX_IRWXO; 235 236 /* Init directory list. */ 237 RTLISTNODE dirList; 238 RTListInit(&dirList); 170 239 171 240 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) … … 175 244 switch (ch) 176 245 { 246 case 'h': 247 VBoxServiceToolboxShowUsage(); 248 return RTEXITCODE_SUCCESS; 249 177 250 case 'p': 178 251 fMakeParentDirs = true; … … 182 255 rc = RTStrToUInt32Ex(ValueUnion.psz, NULL, 8 /* Base */, &newMode); 183 256 if (RT_FAILURE(rc)) /* Only octet based values supported right now! */ 184 VBoxServiceVerbose(0, "mkdir: Mode flag strings not implemented yet!\n"); 257 { 258 RTMsgError("mkdir: Mode flag strings not implemented yet! Use octal numbers instead.\n"); 259 return RTEXITCODE_SYNTAX; 260 } 185 261 break; 186 262 … … 189 265 break; 190 266 267 case 'V': 268 VBoxServiceToolboxShowVersion(); 269 return RTEXITCODE_SUCCESS; 270 191 271 case VINF_GETOPT_NOT_OPTION: 192 272 { 193 rc = RTPathAbs(ValueUnion.psz, szDir, sizeof(szDir)); 194 if (RT_FAILURE(rc)) 195 VBoxServiceError("mkdir: Could not build absolute directory!\n"); 196 /** @todo r=bird: you can make multiple directories just by 197 * adding them to the mkdir command line: 198 * "mkdir foo/ foo/bar foo/bar/wiz" 199 * This will now only create foo/bar/wiz, which will fail 200 * because the two previous steps weren't executed. It 201 * will also leak memory, but that's not important. (Also, 202 * I don't get why we need to call RTPathAbs here as nobody 203 * is going to change the current directory.) */ 273 /* Add path(s) to buffer. This enables processing multiple paths 274 * at once. 275 * 276 * Since the non-options (RTGETOPTINIT_FLAGS_OPTS_FIRST) come last when 277 * processing this loop it's safe to immediately exit on syntax errors 278 * or showing the help text (see above). */ 279 rc = VBoxServiceToolboxPathBufAddPathEntry(&dirList, ValueUnion.psz); 204 280 break; 205 281 } 206 /** @todo r=bird: Missing handling of the standard options 'V' and207 * 'h'. */208 282 209 283 default: … … 219 293 mode_t umaskMode = umask(0); /* Get current umask. */ 220 294 if (newMode) 221 fileMode = newMode;295 dirMode = newMode; 222 296 #endif 223 297 } 224 298 225 rc = fMakeParentDirs ? 226 RTDirCreateFullPath(szDir, fileMode) 227 : RTDirCreate(szDir, fileMode); 228 229 if (RT_SUCCESS(rc) && fVerbose) 230 VBoxServiceVerbose(0, "mkdir: Created directory '%s', mode 0x%RTfmode\n", szDir, fileMode); /** @todo r=bird: drop the 0x here, use %#RTfmode instead. */ 231 else if (RT_FAILURE(rc)) /** @todo Add a switch with more helpful error texts! */ 299 PVBOXSERVICETOOLBOXPATHENTRY pNodeIt; 300 RTListForEach(&dirList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node) 232 301 { 233 PCRTSTATUSMSG pMsg = RTErrGet(rc); 234 if (pMsg) 235 VBoxServiceError("mkdir: Could not create directory: %s\n", pMsg->pszMsgFull); 236 else 237 VBoxServiceError("mkdir: Could not create directory, rc=%Rrc\n", rc); 302 rc = fMakeParentDirs ? 303 RTDirCreateFullPath(pNodeIt->pszName, dirMode) 304 : RTDirCreate(pNodeIt->pszName, dirMode); 305 306 if (RT_SUCCESS(rc) && fVerbose) 307 RTMsgError("mkdir: Created directory 's', mode %#RTfmode\n", pNodeIt->pszName, dirMode); 308 else if (RT_FAILURE(rc)) /** @todo Add a switch with more helpful error texts! */ 309 { 310 PCRTSTATUSMSG pMsg = RTErrGet(rc); 311 if (pMsg) 312 RTMsgError("mkdir: Could not create directory '%s': %s\n", 313 pNodeIt->pszName, pMsg->pszMsgFull); 314 else 315 RTMsgError("mkdir: Could not create directory '%s', rc=%Rrc\n", pNodeIt->pszName, rc); 316 } 238 317 } 239 240 318 } 241 319 else if (fVerbose) 242 VBoxServiceError("mkdir: Failed with rc=%Rrc\n", rc); 243 return rc; 244 } 245 246 247 /** 248 * 249 * 250 * @return int 251 * 252 * @param argc 253 * @param argv 254 */ 255 int VBoxServiceToolboxCat(int argc, char **argv) 320 RTMsgError("mkdir: Failed with rc=%Rrc\n", rc); 321 322 VBoxServiceToolboxPathBufDestroy(&dirList); 323 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 324 } 325 326 327 /** 328 * Main function for tool "vbox_cat". 329 * 330 * @return RTEXITCODE. 331 * @param argc Number of arguments. 332 * @param argv Pointer to argument array. 333 */ 334 static int VBoxServiceToolboxCat(int argc, char **argv) 256 335 { 257 336 static const RTGETOPTDEF s_aOptions[] = 258 337 { 259 { "--input", 'i', RTGETOPT_REQ_STRING }, 260 { "--output", 'o', RTGETOPT_REQ_STRING }, 261 { "--flags", 'f', RTGETOPT_REQ_STRING } 262 /** @todo r=bird: Missing options 'A', 'b', 'e', 'E', 'n', 's', 'T', 263 * 'u', 'v' as found on 'man cat' on a linux system. They must 264 * not be implemented, just return an apologetic error message. */ 338 /* Sorted by short ops. */ 339 { "--show-all", 'a', RTGETOPT_REQ_NOTHING }, 340 { "--number-nonblank", 'b', RTGETOPT_REQ_NOTHING }, 341 { NULL, 'e', RTGETOPT_REQ_NOTHING }, 342 { NULL, 'E', RTGETOPT_REQ_NOTHING }, 343 { "--flags", 'f', RTGETOPT_REQ_STRING }, 344 { "--no-content-indexed", CAT_OPT_NO_CONTENT_INDEXED, RTGETOPT_REQ_NOTHING }, 345 { "--number", 'n', RTGETOPT_REQ_NOTHING }, 346 { "--output", 'o', RTGETOPT_REQ_STRING }, 347 { "--squeeze-blank", 's', RTGETOPT_REQ_NOTHING }, 348 { NULL, 't', RTGETOPT_REQ_NOTHING }, 349 { "--show-tabs", 'T', RTGETOPT_REQ_NOTHING }, 350 { NULL, 'u', RTGETOPT_REQ_NOTHING }, 351 { "--show-noneprinting", 'v', RTGETOPT_REQ_NOTHING } 265 352 }; 266 267 353 268 354 int ch; … … 272 358 273 359 int rc = VINF_SUCCESS; 274 RTFILE hInput = NIL_RTFILE; 275 360 bool fUsageOK = true; 361 362 char szOutput[RTPATH_MAX] = { 0 }; 276 363 RTFILE hOutput = NIL_RTFILE; 277 364 uint32_t fFlags = RTFILE_O_CREATE_REPLACE /* Output file flags. */ 278 365 | RTFILE_O_WRITE 279 366 | RTFILE_O_DENY_WRITE; 367 368 /* Init directory list. */ 369 RTLISTNODE inputList; 370 RTListInit(&inputList); 280 371 281 372 while ( (ch = RTGetOpt(&GetState, &ValueUnion)) … … 285 376 switch (ch) 286 377 { 287 /** @todo r=bird: You add a flag --no-content-indexed without a 288 * short form (use a #define CAT_OPT_NO_CONTENT_INDEXED 1000 for 289 * iShort). */ 290 291 case 'f': 292 /* Process flags; no fancy parsing here yet. */ 293 if (RTStrIStr(ValueUnion.psz, "noindex")) 294 fFlags |= RTFILE_O_NOT_CONTENT_INDEXED; 295 else 296 { 297 VBoxServiceError("cat: Unknown flag set!\n"); 298 rc = VERR_INVALID_PARAMETER; 299 } 300 break; 378 case 'a': 379 case 'b': 380 case 'e': 381 case 'E': 382 case 'n': 383 case 's': 384 case 't': 385 case 'T': 386 case 'v': 387 RTMsgError("cat: Sorry, option '%s' is not implemented yet!\n", 388 ValueUnion.pDef->pszLong); 389 rc = VERR_INVALID_PARAMETER; 390 break; 391 392 case 'h': 393 VBoxServiceToolboxShowUsage(); 394 return RTEXITCODE_SUCCESS; 301 395 302 396 case 'o': 303 rc = RTFileOpen(&hOutput, ValueUnion.psz, fFlags); 304 if (RT_FAILURE(rc)) 305 VBoxServiceError("cat: Could not create output file \"%s\"! rc=%Rrc\n", 306 ValueUnion.psz, rc); 307 break; 308 309 /** @todo r=bird: Again, there shall be no need for any -i 310 * options since all non-options are input files. */ 311 312 case 'i': 397 if (!RTStrPrintf(szOutput, sizeof(szOutput), ValueUnion.psz)) 398 rc = VERR_NO_MEMORY; 399 break; 400 401 case 'u': 402 /* Ignored. */ 403 break; 404 405 case 'V': 406 VBoxServiceToolboxShowVersion(); 407 return RTEXITCODE_SUCCESS; 408 409 case CAT_OPT_NO_CONTENT_INDEXED: 410 fFlags |= RTFILE_O_NOT_CONTENT_INDEXED; 411 break; 412 313 413 case VINF_GETOPT_NOT_OPTION: 314 414 { 315 rc = RTFileOpen(&hInput, ValueUnion.psz, 316 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 317 if (RT_FAILURE(rc)) 318 VBoxServiceError("cat: Could not open input file \"%s\"! rc=%Rrc\n", 319 ValueUnion.psz, rc); 415 /* Add file(s) to buffer. This enables processing multiple paths 416 * at once. 417 * 418 * Since the non-options (RTGETOPTINIT_FLAGS_OPTS_FIRST) come last when 419 * processing this loop it's safe to immediately exit on syntax errors 420 * or showing the help text (see above). */ 421 rc = VBoxServiceToolboxPathBufAddPathEntry(&inputList, ValueUnion.psz); 320 422 break; 321 423 } 322 323 /** @todo r=bird: Missing handling of the standard options 'V' and324 * 'h'. */325 424 326 425 default: … … 330 429 331 430 if (RT_SUCCESS(rc)) 332 rc = VBoxServiceToolboxCatOutput(hInput, hOutput); 333 334 if (hInput != NIL_RTFILE) 335 RTFileClose(hInput); 431 { 432 if (strlen(szOutput)) 433 { 434 rc = RTFileOpen(&hOutput, szOutput, fFlags); 435 if (RT_FAILURE(rc)) 436 RTMsgError("cat: Could not create output file '%s'! rc=%Rrc\n", 437 szOutput, rc); 438 } 439 440 if (RT_SUCCESS(rc)) 441 { 442 /* Process each input file. */ 443 PVBOXSERVICETOOLBOXPATHENTRY pNodeIt; 444 RTFILE hInput = NIL_RTFILE; 445 RTListForEach(&inputList, pNodeIt, VBOXSERVICETOOLBOXPATHENTRY, Node) 446 { 447 rc = RTFileOpen(&hInput, pNodeIt->pszName, 448 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 449 if (RT_SUCCESS(rc)) 450 { 451 rc = VBoxServiceToolboxCatOutput(hInput, hOutput); 452 RTFileClose(hInput); 453 } 454 else 455 { 456 PCRTSTATUSMSG pMsg = RTErrGet(rc); 457 if (pMsg) 458 RTMsgError("cat: Could not open input file '%s': %s\n", 459 pNodeIt->pszName, pMsg->pszMsgFull); 460 else 461 RTMsgError("cat: Could not open input file '%s', rc=%Rrc\n", pNodeIt->pszName, rc); 462 } 463 464 if (RT_FAILURE(rc)) 465 break; 466 } 467 468 /* If not input files were defined, process stdin. */ 469 if (RTListNodeIsFirst(&inputList, &inputList)) 470 rc = VBoxServiceToolboxCatOutput(hInput, hOutput); 471 } 472 } 473 336 474 if (hOutput != NIL_RTFILE) 337 475 RTFileClose(hOutput); 338 return rc; 339 } 340 341 342 /** 343 * Main routine for toolbox command line handling. 344 * 345 * @return int 346 * 347 * @param argc 348 * @param argv 349 */ 350 int VBoxServiceToolboxMain(int argc, char **argv) 351 { 352 /** @todo r=bird: The return type of this function is mixed; both RTEXITCODE 353 * and IPRT status code. That doesn't cut it. The RTEXITCODE part should 354 * be returned separately from the handled-or-unhandled bit. 355 * 356 * Also, please change VBoxServiceToolboxCat and VBoxServiceToolboxMkDir to 357 * return RTEXITCODE and use RTMsg* like RTZipTarCmd (and later 358 * RTZipGzipCmd). */ 359 int rc = VERR_NOT_FOUND; 476 VBoxServiceToolboxPathBufDestroy(&inputList); 477 478 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 479 } 480 481 482 /** 483 * Entry point for internal toolbox. 484 * 485 * @return True if an internal tool was handled, false if not. 486 * @param argc Number of arguments. 487 * @param argv Pointer to argument array. 488 * @param piExitCode Pointer to receive exit code when internal command 489 * was handled. 490 */ 491 bool VBoxServiceToolboxMain(int argc, char **argv, int *piExitCode) 492 { 360 493 if (argc > 0) /* Do we have at least a main command? */ 361 494 { … … 363 496 || !strcmp(argv[0], "vbox_cat")) 364 497 { 365 rc = VBoxServiceToolboxCat(argc, argv); 498 *piExitCode = VBoxServiceToolboxCat(argc, argv); 499 return true; 366 500 } 367 501 else if ( !strcmp(argv[0], "mkdir") 368 502 || !strcmp(argv[0], "vbox_mkdir")) 369 503 { 370 rc = VBoxServiceToolboxMkDir(argc, argv); 504 *piExitCode = VBoxServiceToolboxMkDir(argc, argv); 505 return true; 371 506 } 372 507 } 373 374 if (rc != VERR_NOT_FOUND) 375 rc = RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; 376 return rc; 377 } 378 508 return false; 509 } 510
Note:
See TracChangeset
for help on using the changeset viewer.