Changeset 44299 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jan 15, 2013 2:58:38 PM (12 years ago)
- Location:
- trunk/src/VBox/Runtime/common
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/getopt.cpp
r42129 r44299 792 792 RTMsgError("Unknown option: '%s'", pValueUnion->psz); 793 793 else if (ch == VERR_GETOPT_INVALID_ARGUMENT_FORMAT) 794 /** @todo r=klaus not really ideal, as the optionisn't available */795 RTMsgError(" Invalid argument format: '%s'", pValueUnion->psz);794 /** @todo r=klaus not really ideal, as the value isn't available */ 795 RTMsgError("The value given '%s' has an invalid format.", pValueUnion->pDef->pszLong); 796 796 else if (pValueUnion->pDef) 797 797 RTMsgError("%s: %Rrs\n", pValueUnion->pDef->pszLong, ch); -
trunk/src/VBox/Runtime/common/zip/tarcmd.cpp
r44278 r44299 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - TAR Command.3 * IPRT - A mini TAR Command. 4 4 */ 5 5 … … 34 34 #include <iprt/buildconfig.h> 35 35 #include <iprt/ctype.h> 36 #include <iprt/dir.h> 36 37 #include <iprt/file.h> 37 38 #include <iprt/getopt.h> … … 40 41 #include <iprt/message.h> 41 42 #include <iprt/param.h> 43 #include <iprt/path.h> 42 44 #include <iprt/stream.h> 43 45 #include <iprt/string.h> 46 #include <iprt/symlink.h> 44 47 #include <iprt/vfs.h> 45 48 … … 48 51 * Defined Constants And Macros * 49 52 *******************************************************************************/ 50 #define RTZIPTARCMD_OPT_DELETE 1000 51 #define RTZIPTARCMD_OPT_OWNER 1001 52 #define RTZIPTARCMD_OPT_GROUP 1002 53 #define RTZIPTARCMD_OPT_UTC 1003 54 #define RTZIPTARCMD_OPT_PREFIX 1004 53 #define RTZIPTARCMD_OPT_DELETE 1000 54 #define RTZIPTARCMD_OPT_OWNER 1001 55 #define RTZIPTARCMD_OPT_GROUP 1002 56 #define RTZIPTARCMD_OPT_UTC 1003 57 #define RTZIPTARCMD_OPT_PREFIX 1004 58 #define RTZIPTARCMD_OPT_FILE_MODE_AND_MASK 1005 59 #define RTZIPTARCMD_OPT_FILE_MODE_OR_MASK 1006 60 #define RTZIPTARCMD_OPT_DIR_MODE_AND_MASK 1007 61 #define RTZIPTARCMD_OPT_DIR_MODE_OR_MASK 1008 55 62 56 63 … … 74 81 /** Whether we're verbose or quiet. */ 75 82 bool fVerbose; 76 /** Whether to preserve permissions when restoring. */ 77 bool fPreservePermissions; 83 /** Whether to preserve the original file owner when restoring. */ 84 bool fPreserveOwner; 85 /** Whether to preserve the original file group when restoring. */ 86 bool fPreserveGroup; 87 /** Whether to skip restoring the modification time (only time stored by the 88 * traditional TAR format). */ 89 bool fNoModTime; 78 90 /** The compressor/decompressor method to employ (0, z or j). */ 79 91 char chZipper; 80 92 81 /** The owner to set. */ 93 /** The owner to set. NULL if not applicable. 94 * Always resolved into uidOwner for extraction. */ 82 95 const char *pszOwner; 83 /** The owner ID to set when unpacking if pszOwner is not NULL. */96 /** The owner ID to set. NIL_RTUID if not applicable. */ 84 97 RTUID uidOwner; 85 /** The group to set. */ 98 /** The group to set. NULL if not applicable. 99 * Always resolved into gidGroup for extraction. */ 86 100 const char *pszGroup; 87 /** The group ID to set when unpacking if pszGroup is not NULL. */101 /** The group ID to set. NIL_RTGUID if not applicable. */ 88 102 RTGID gidGroup; 89 103 /** Display the modification times in UTC instead of local time. */ 90 104 bool fDisplayUtc; 105 /** File mode AND mask. */ 106 RTFMODE fFileModeAndMask; 107 /** File mode OR mask. */ 108 RTFMODE fFileModeOrMask; 109 /** Directory mode AND mask. */ 110 RTFMODE fDirModeAndMask; 111 /** Directory mode OR mask. */ 112 RTFMODE fDirModeOrMask; 91 113 92 114 /** What to prefix all names with when creating, adding, whatever. */ … … 101 123 /** Pointer to the IPRT tar options. */ 102 124 typedef RTZIPTARCMDOPS *PRTZIPTARCMDOPS; 125 126 /** 127 * Callback used by rtZipTarDoWithMembers 128 * 129 * @returns rcExit or RTEXITCODE_FAILURE. 130 * @param pOpts The tar options. 131 * @param hVfsObj The tar object to display 132 * @param pszName The name. 133 * @param rcExit The current exit code. 134 */ 135 typedef RTEXITCODE (*PFNDOWITHMEMBER)(PRTZIPTARCMDOPS pOpts, RTVFSOBJ hVfsObj, const char *pszName, RTEXITCODE rcExit); 103 136 104 137 … … 226 259 227 260 /** 228 * Display a tar entry in the verbose form. 261 * Worker for the --list and --extract commands. 262 * 263 * @returns The appropriate exit code. 264 * @param pOpts The tar options. 265 * @param pfnCallback The command specific callback. 266 */ 267 static RTEXITCODE rtZipTarDoWithMembers(PRTZIPTARCMDOPS pOpts, PFNDOWITHMEMBER pfnCallback) 268 { 269 /* 270 * Allocate a bitmap to go with the file list. This will be used to 271 * indicate which files we've processed and which not. 272 */ 273 uint32_t *pbmFound = NULL; 274 if (pOpts->cFiles) 275 { 276 pbmFound = (uint32_t *)RTMemAllocZ(((pOpts->cFiles + 31) / 32) * sizeof(uint32_t)); 277 if (!pbmFound) 278 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to allocate the found-file-bitmap"); 279 } 280 281 282 /* 283 * Open the input archive. 284 */ 285 RTVFSFSSTREAM hVfsFssIn; 286 RTEXITCODE rcExit = rtZipTarCmdOpenInputArchive(pOpts, &hVfsFssIn); 287 if (rcExit == RTEXITCODE_SUCCESS) 288 { 289 /* 290 * Process the stream. 291 */ 292 for (;;) 293 { 294 /* 295 * Retrive the next object. 296 */ 297 char *pszName; 298 RTVFSOBJ hVfsObj; 299 int rc = RTVfsFsStrmNext(hVfsFssIn, &pszName, NULL, &hVfsObj); 300 if (RT_FAILURE(rc)) 301 { 302 if (rc != VERR_EOF) 303 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsFsStrmNext returned %Rrc", rc); 304 break; 305 } 306 307 /* 308 * Should we process this entry? 309 */ 310 uint32_t iFile = UINT32_MAX; 311 if ( !pOpts->cFiles 312 || rtZipTarCmdIsNameInArray(pszName, pOpts->papszFiles, &iFile) ) 313 { 314 if (pbmFound) 315 ASMBitSet(pbmFound, iFile); 316 317 rcExit = pfnCallback(pOpts, hVfsObj, pszName, rcExit); 318 } 319 320 /* 321 * Release the current object and string. 322 */ 323 RTVfsObjRelease(hVfsObj); 324 RTStrFree(pszName); 325 } 326 327 /* 328 * Complain about any files we didn't find. 329 */ 330 for (uint32_t iFile = 0; iFile < pOpts->cFiles; iFile++) 331 if (!ASMBitTest(pbmFound, iFile)) 332 { 333 RTMsgError("%s: Was not found in the archive", pOpts->papszFiles[iFile]); 334 rcExit = RTEXITCODE_FAILURE; 335 } 336 } 337 RTMemFree(pbmFound); 338 return rcExit; 339 } 340 341 342 /** 343 * Checks if the name contains any escape sequences. 344 * 345 * An escape sequence would generally be one or more '..' references. On DOS 346 * like system, something that would make up a drive letter reference is also 347 * considered an escape sequence. 348 * 349 * @returns true / false. 350 * @param pszName The name to consider. 351 */ 352 static bool rtZipTarHasEscapeSequence(const char *pszName) 353 { 354 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) 355 if (pszName[0] == ':') 356 return true; 357 #endif 358 while (*pszName) 359 { 360 while (RTPATH_IS_SEP(*pszName)) 361 pszName++; 362 if ( pszName[0] == '.' 363 && pszName[1] == '.' 364 && (pszName[2] == '\0' || RTPATH_IS_SLASH(pszName[2])) ) 365 return true; 366 while (*pszName && !RTPATH_IS_SEP(*pszName)) 367 pszName++; 368 } 369 370 return false; 371 } 372 373 374 /** 375 * Queries the user ID to use when extracting a member. 229 376 * 230 377 * @returns rcExit or RTEXITCODE_FAILURE. 378 * @param pOpts The tar options. 379 * @param pUser The user info. 380 * @param pszName The file name to use when complaining. 231 381 * @param rcExit The current exit code. 382 * @param pUid Where to return the user ID. 383 */ 384 static RTEXITCODE rtZipTarQueryExtractOwner(PRTZIPTARCMDOPS pOpts, PCRTFSOBJINFO pOwner, const char *pszName, RTEXITCODE rcExit, 385 PRTUID pUid) 386 { 387 if (pOpts->uidOwner != NIL_RTUID) 388 *pUid = pOpts->uidOwner; 389 else if (pOpts->fPreserveGroup) 390 { 391 if (!pOwner->Attr.u.UnixGroup.szName[0]) 392 *pUid = pOwner->Attr.u.UnixOwner.uid; 393 else 394 { 395 *pUid = NIL_RTUID; 396 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: User resolving is not implemented.", pszName); 397 } 398 } 399 else 400 *pUid = NIL_RTUID; 401 return rcExit; 402 } 403 404 405 /** 406 * Queries the group ID to use when extracting a member. 407 * 408 * @returns rcExit or RTEXITCODE_FAILURE. 409 * @param pOpts The tar options. 410 * @param pGroup The group info. 411 * @param pszName The file name to use when complaining. 412 * @param rcExit The current exit code. 413 * @param pGid Where to return the group ID. 414 */ 415 static RTEXITCODE rtZipTarQueryExtractGroup(PRTZIPTARCMDOPS pOpts, PCRTFSOBJINFO pGroup, const char *pszName, RTEXITCODE rcExit, 416 PRTGID pGid) 417 { 418 if (pOpts->gidGroup != NIL_RTGID) 419 *pGid = pOpts->gidGroup; 420 else if (pOpts->fPreserveGroup) 421 { 422 if (!pGroup->Attr.u.UnixGroup.szName[0]) 423 *pGid = pGroup->Attr.u.UnixGroup.gid; 424 else 425 { 426 *pGid = NIL_RTGID; 427 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Group resolving is not implemented.", pszName); 428 } 429 } 430 else 431 *pGid = NIL_RTGID; 432 return rcExit; 433 } 434 435 436 437 /** 438 * Extracts a file. 439 * 440 * Since we can restore permissions and attributes more efficiently by working 441 * directly on the file handle, we have special code path for files. 442 * 443 * @returns rcExit or RTEXITCODE_FAILURE. 444 * @param pOpts The tar options. 232 445 * @param hVfsObj The tar object to display 233 * @param pszName The name. 234 * @param pOpts The tar options. 235 */ 236 static RTEXITCODE rtZipTarCmdDisplayEntryVerbose(RTEXITCODE rcExit, RTVFSOBJ hVfsObj, const char *pszName, 237 PRTZIPTARCMDOPS pOpts) 446 * @param rcExit The current exit code. 447 * @param pUnixInfo The unix fs object info. 448 * @param pOwner The owner info. 449 * @param pGroup The group info. 450 */ 451 static RTEXITCODE rtZipTarCmdExtractFile(PRTZIPTARCMDOPS pOpts, RTVFSOBJ hVfsObj, RTEXITCODE rcExit, 452 const char *pszDst, PCRTFSOBJINFO pUnixInfo, PCRTFSOBJINFO pOwner, PCRTFSOBJINFO pGroup) 238 453 { 454 /* 455 * Open the destination file and create a stream object for it. 456 */ 457 uint32_t fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_ACCESS_ATTR_DEFAULT 458 | ((RTFS_UNIX_IWUSR | RTFS_UNIX_IRUSR) << RTFILE_O_CREATE_MODE_SHIFT); 459 RTFILE hFile; 460 int rc = RTFileOpen(&hFile, pszDst, fOpen); 461 if (RT_FAILURE(rc)) 462 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error creating file: %Rrc", pszDst, rc); 463 464 RTVFSIOSTREAM hVfsIosDst; 465 rc = RTVfsIoStrmFromRTFile(hFile, fOpen, true /*fLeaveOpen*/, &hVfsIosDst); 466 if (RT_SUCCESS(rc)) 467 { 468 /* 469 * Pump the data thru. 470 */ 471 RTVFSIOSTREAM hVfsIosSrc = RTVfsObjToIoStream(hVfsObj); 472 rc = RTVfsUtilPumpIoStreams(hVfsIosSrc, hVfsIosDst, (uint32_t)RT_MIN(pUnixInfo->cbObject, _1M)); 473 if (RT_SUCCESS(rc)) 474 { 475 /* 476 * Correct the file mode and other attributes. 477 */ 478 if (!pOpts->fNoModTime) 479 { 480 rc = RTFileSetTimes(hFile, NULL, &pUnixInfo->ModificationTime, NULL, NULL); 481 if (RT_FAILURE(rc)) 482 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error setting times: %Rrc", pszDst, rc); 483 } 484 485 #if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2) 486 if ( pOpts->uidOwner != NIL_RTUID 487 || pOpts->gidGroup != NIL_RTGID 488 || pOpts->fPreserveOwner 489 || pOpts->fPreserveGroup) 490 { 491 RTUID uidFile; 492 rcExit = rtZipTarQueryExtractOwner(pOpts, pOwner, pszDst, rcExit, &uidFile); 493 494 RTGID gidFile; 495 rcExit = rtZipTarQueryExtractGroup(pOpts, pGroup, pszDst, rcExit, &gidFile); 496 if (uidFile != NIL_RTUID || gidFile != NIL_RTGID) 497 { 498 rc = RTFileSetOwner(hFile, uidFile, gidFile); 499 if (RT_FAILURE(rc)) 500 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error owner/group: %Rrc", pszDst, rc); 501 } 502 } 503 #endif 504 505 RTFMODE fMode = (pUnixInfo->Attr.fMode & pOpts->fFileModeAndMask) | pOpts->fFileModeOrMask; 506 rc = RTFileSetMode(hFile, fMode | RTFS_TYPE_FILE); 507 if (RT_FAILURE(rc)) 508 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error changing mode: %Rrc", pszDst, rc); 509 } 510 else 511 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error writing out file: %Rrc", pszDst, rc); 512 RTVfsIoStrmRelease(hVfsIosSrc); 513 RTVfsIoStrmRelease(hVfsIosDst); 514 } 515 else 516 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error creating I/O stream for file: %Rrc", pszDst, rc); 517 RTFileClose(hFile); 518 return rcExit; 519 } 520 521 522 /** 523 * @callback_method_impl{PFNDOWITHMEMBER, Implements --extract.} 524 */ 525 static RTEXITCODE rtZipTarCmdExtractCallback(PRTZIPTARCMDOPS pOpts, RTVFSOBJ hVfsObj, const char *pszName, RTEXITCODE rcExit) 526 { 527 if (pOpts->fVerbose) 528 RTPrintf("%s\n", pszName); 529 530 /* 531 * Query all the information. 532 */ 533 RTFSOBJINFO UnixInfo; 534 int rc = RTVfsObjQueryInfo(hVfsObj, &UnixInfo, RTFSOBJATTRADD_UNIX); 535 if (RT_FAILURE(rc)) 536 return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsObjQueryInfo returned %Rrc on '%s'", rc, pszName); 537 538 RTFSOBJINFO Owner; 539 rc = RTVfsObjQueryInfo(hVfsObj, &Owner, RTFSOBJATTRADD_UNIX_OWNER); 540 if (RT_FAILURE(rc)) 541 return RTMsgErrorExit(RTEXITCODE_FAILURE, 542 "RTVfsObjQueryInfo(,,UNIX_OWNER) returned %Rrc on '%s'", 543 rc, pszName); 544 545 RTFSOBJINFO Group; 546 rc = RTVfsObjQueryInfo(hVfsObj, &Group, RTFSOBJATTRADD_UNIX_GROUP); 547 if (RT_FAILURE(rc)) 548 return RTMsgErrorExit(RTEXITCODE_FAILURE, 549 "RTVfsObjQueryInfo(,,UNIX_OWNER) returned %Rrc on '%s'", 550 rc, pszName); 551 552 const char *pszLinkType = NULL; 553 char szTarget[RTPATH_MAX]; 554 szTarget[0] = '\0'; 555 RTVFSSYMLINK hVfsSymlink = RTVfsObjToSymlink(hVfsObj); 556 if (hVfsSymlink != NIL_RTVFSSYMLINK) 557 { 558 rc = RTVfsSymlinkRead(hVfsSymlink, szTarget, sizeof(szTarget)); 559 RTVfsSymlinkRelease(hVfsSymlink); 560 if (RT_FAILURE(rc)) 561 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: RTVfsSymlinkRead failed: %Rrc", pszName, rc); 562 if (!RTFS_IS_SYMLINK(UnixInfo.Attr.fMode)) 563 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Hardlinks are not supported.", pszName); 564 if (!szTarget[0]) 565 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Link target is empty.", pszName); 566 } 567 else if (RTFS_IS_SYMLINK(UnixInfo.Attr.fMode)) 568 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to get symlink object for '%s'", pszName); 569 570 if (rtZipTarHasEscapeSequence(pszName)) 571 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Name '%s' contains an escape sequence.", pszName); 572 573 /* 574 * Construct the path to the extracted member. 575 */ 576 char szDst[RTPATH_MAX]; 577 rc = RTPathJoin(szDst, sizeof(szDst), pOpts->pszDirectory ? pOpts->pszDirectory : ".", pszName); 578 if (RT_FAILURE(rc)) 579 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to construct destination path for: %Rrc", pszName, rc); 580 581 /* 582 * Extract according to the type. 583 */ 584 switch (UnixInfo.Attr.fMode & RTFS_TYPE_MASK) 585 { 586 case RTFS_TYPE_FILE: 587 return rtZipTarCmdExtractFile(pOpts, hVfsObj, rcExit, szDst, &UnixInfo, &Owner, &Group); 588 589 case RTFS_TYPE_DIRECTORY: 590 rc = RTDirCreateFullPath(szDst, UnixInfo.Attr.fMode & RTFS_UNIX_ALL_ACCESS_PERMS); 591 if (RT_FAILURE(rc)) 592 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error creating directory: %Rrc", szDst, rc); 593 break; 594 595 case RTFS_TYPE_SYMLINK: 596 rc = RTSymlinkCreate(szDst, szTarget, RTSYMLINKTYPE_UNKNOWN, 0); 597 if (RT_FAILURE(rc)) 598 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error creating symbolic link: %Rrc", szDst, rc); 599 break; 600 601 case RTFS_TYPE_FIFO: 602 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: FIFOs are not supported.", pszName); 603 case RTFS_TYPE_DEV_CHAR: 604 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: FIFOs are not supported.", pszName); 605 case RTFS_TYPE_DEV_BLOCK: 606 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Block devices are not supported.", pszName); 607 case RTFS_TYPE_SOCKET: 608 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Sockets are not supported.", pszName); 609 case RTFS_TYPE_WHITEOUT: 610 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Whiteouts are not support.", pszName); 611 default: 612 return RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Unknown file type.", pszName); 613 } 614 615 /* 616 * Set other attributes as requested . 617 * . 618 * Note! File extraction does get here. 619 */ 620 if (!pOpts->fNoModTime) 621 { 622 rc = RTPathSetTimesEx(szDst, NULL, &UnixInfo.ModificationTime, NULL, NULL, RTPATH_F_ON_LINK); 623 if (RT_FAILURE(rc) && rc != VERR_NOT_SUPPORTED && rc != VERR_NS_SYMLINK_SET_TIME) 624 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error changing modification time: %Rrc.", pszName, rc); 625 } 626 627 #if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2) 628 if ( pOpts->uidOwner != NIL_RTUID 629 || pOpts->gidGroup != NIL_RTGID 630 || pOpts->fPreserveOwner 631 || pOpts->fPreserveGroup) 632 { 633 RTUID uidFile; 634 rcExit = rtZipTarQueryExtractOwner(pOpts, &Owner, szDst, rcExit, &uidFile); 635 636 RTGID gidFile; 637 rcExit = rtZipTarQueryExtractGroup(pOpts, &Group, szDst, rcExit, &gidFile); 638 if (uidFile != NIL_RTUID || gidFile != NIL_RTGID) 639 { 640 rc = RTPathSetOwnerEx(szDst, uidFile, gidFile, RTPATH_F_ON_LINK); 641 if (RT_FAILURE(rc)) 642 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error owner/group: %Rrc", szDst, rc); 643 } 644 } 645 #endif 646 647 if (!RTFS_IS_SYMLINK(UnixInfo.Attr.fMode)) /* RTPathSetMode follows symbolic links atm. */ 648 { 649 RTFMODE fMode; 650 if (RTFS_IS_DIRECTORY(UnixInfo.Attr.fMode)) 651 fMode = (UnixInfo.Attr.fMode & (pOpts->fDirModeAndMask | RTFS_TYPE_MASK)) | pOpts->fDirModeOrMask; 652 else 653 fMode = (UnixInfo.Attr.fMode & (pOpts->fFileModeAndMask | RTFS_TYPE_MASK)) | pOpts->fFileModeOrMask; 654 rc = RTPathSetMode(szDst, fMode); 655 if (RT_FAILURE(rc)) 656 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Error changing mode: %Rrc", szDst, rc); 657 } 658 659 return rcExit; 660 } 661 662 663 /** 664 * @callback_method_impl{PFNDOWITHMEMBER, Implements --list.} 665 */ 666 static RTEXITCODE rtZipTarCmdListCallback(PRTZIPTARCMDOPS pOpts, RTVFSOBJ hVfsObj, const char *pszName, RTEXITCODE rcExit) 667 { 668 /* 669 * This is very simple in non-verbose mode. 670 */ 671 if (!pOpts->fVerbose) 672 { 673 RTPrintf("%s\n", pszName); 674 return rcExit; 675 } 676 239 677 /* 240 678 * Query all the information. … … 393 831 } 394 832 833 395 834 /** 396 * Implements the -t/--list operation. 397 * 398 * @returns The appropriate exit code. 399 * @param pOpts The tar options. 400 */ 401 static RTEXITCODE rtZipTarCmdList(PRTZIPTARCMDOPS pOpts) 835 * Display usage. 836 * 837 * @param pszProgName The program name. 838 */ 839 static void rtZipTarUsage(const char *pszProgName) 402 840 { 403 841 /* 404 * Allocate a bitmap to go with the file list. This will be used to 405 * indicate which files we've processed and which not. 406 */ 407 uint32_t *pbmFound = NULL; 408 if (pOpts->cFiles) 409 { 410 pbmFound = (uint32_t *)RTMemAllocZ(((pOpts->cFiles + 31) / 32) * sizeof(uint32_t)); 411 if (!pbmFound) 412 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to allocate the found-file-bitmap"); 413 } 414 415 416 /* 417 * Open the input archive. 418 */ 419 RTVFSFSSTREAM hVfsFssIn; 420 RTEXITCODE rcExit = rtZipTarCmdOpenInputArchive(pOpts, &hVfsFssIn); 421 if (rcExit == RTEXITCODE_SUCCESS) 422 { 423 /* 424 * Process the stream. 425 */ 426 for (;;) 427 { 428 /* 429 * Retrive the next object. 430 */ 431 char *pszName; 432 RTVFSOBJ hVfsObj; 433 int rc = RTVfsFsStrmNext(hVfsFssIn, &pszName, NULL, &hVfsObj); 434 if (RT_FAILURE(rc)) 435 { 436 if (rc != VERR_EOF) 437 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsFsStrmNext returned %Rrc", rc); 438 break; 439 } 440 441 /* 442 * Should we display this entry? 443 */ 444 uint32_t iFile = UINT32_MAX; 445 if ( !pOpts->cFiles 446 || rtZipTarCmdIsNameInArray(pszName, pOpts->papszFiles, &iFile) ) 447 { 448 if (pbmFound) 449 ASMBitSet(pbmFound, iFile); 450 451 if (!pOpts->fVerbose) 452 RTPrintf("%s\n", pszName); 453 else 454 rcExit = rtZipTarCmdDisplayEntryVerbose(rcExit, hVfsObj, pszName, pOpts); 455 } 456 457 /* 458 * Release the current object and string. 459 */ 460 RTVfsObjRelease(hVfsObj); 461 RTStrFree(pszName); 462 } 463 464 /* 465 * Complain about any files we didn't find. 466 */ 467 for (uint32_t iFile = 0; iFile < pOpts->cFiles; iFile++) 468 if (!ASMBitTest(pbmFound, iFile)) 469 { 470 RTMsgError("%s: Was not found in the archive", pOpts->papszFiles[iFile]); 471 rcExit = RTEXITCODE_FAILURE; 472 } 473 } 474 RTMemFree(pbmFound); 475 return rcExit; 842 * 0 1 2 3 4 5 6 7 8 843 * 012345678901234567890123456789012345678901234567890123456789012345678901234567890 844 */ 845 RTPrintf("Usage: %s [options]\n" 846 "\n", 847 pszProgName); 848 RTPrintf("Operations:\n" 849 " -A, --concatenate, --catenate\n" 850 " Append the content of one tar archive to another. (not impl)\n" 851 " -c, --create\n" 852 " Create a new tar archive. (not impl)\n" 853 " -d, --diff, --compare\n" 854 " Compare atar archive with the file system. (not impl)\n" 855 " -r, --append\n" 856 " Append more files to the tar archive. (not impl)\n" 857 " -t, --list\n" 858 " List the contents of the tar archive.\n" 859 " -u, --update\n" 860 " Update the archive, adding files that are newer than the\n" 861 " ones in the archive. (not impl)\n" 862 " -x, --extract, --get\n" 863 " Extract the files from the tar archive.\n" 864 " --delete\n" 865 " Delete files from the tar archive.\n" 866 "\n" 867 ); 868 RTPrintf("Basic Options:\n" 869 " -C <dir>, --directory <dir> (-A, -C, -d, -r, -u, -x)\n" 870 " Sets the base directory for input and output file members.\n" 871 " This does not apply to --file, even if it preceeds it.\n" 872 " -f <archive>, --file <archive> (all)\n" 873 " The tar file to create or process. '-' indicates stdout/stdin,\n" 874 " which is is the default.\n" 875 " -v, --verbose (all)\n" 876 " Verbose operation.\n" 877 " -p, --preserve-permissions (-x)\n" 878 " Preserve all permissions when extracting. Must be used\n" 879 " before the mode mask options as it will change some of these.\n" 880 " -j, --bzip2 (all)\n" 881 " Compress/decompress the archive with bzip2.\n" 882 " -z, --gzip, --gunzip, --ungzip (all)\n" 883 " Compress/decompress the archive with gzip.\n" 884 "\n"); 885 RTPrintf("Misc Options:\n" 886 " --owner <uid/username> (-A, -C, -d, -r, -u, -x)\n" 887 " Set the owner of extracted and archived files to the user specified.\n" 888 " --group <uid/username> (-A, -C, -d, -r, -u, -x)\n" 889 " Set the group of extracted and archived files to the group specified.\n" 890 " --utc (-t)\n" 891 " Display timestamps as UTC instead of local time.\n" 892 "\n"); 893 RTPrintf("IPRT Options:\n" 894 " --prefix <dir-prefix> (-A, -C, -d, -r, -u)\n" 895 " Directory prefix to give the members added to the archive.\n" 896 " --file-mode-and-mask <octal-mode> (-A, -C, -d, -r, -u, -x)\n" 897 " Restrict the access mode of regular and special files.\n" 898 " --file-mode-and-mask <octal-mode> (-A, -C, -d, -r, -u, -x)\n" 899 " Include the given access mode for regular and special files.\n" 900 " --dir-mode-and-mask <octal-mode> (-A, -C, -d, -r, -u, -x)\n" 901 " Restrict the access mode of directories.\n" 902 " --dir-mode-and-mask <octal-mode> (-A, -C, -d, -r, -u, -x)\n" 903 " Include the given access mode for directories.\n" 904 "\n"); 905 RTPrintf("Standard Options:\n" 906 " -h, -?, --help\n" 907 " Display this help text.\n" 908 " -V, --version\n" 909 " Display version number.\n"); 476 910 } 477 478 479 911 480 912 RTDECL(RTEXITCODE) RTZipTarCmd(unsigned cArgs, char **papszArgs) … … 518 950 519 951 /* IPRT extensions */ 520 { "--prefix", RTZIPTARCMD_OPT_PREFIX, RTGETOPT_REQ_STRING }, 952 { "--prefix", RTZIPTARCMD_OPT_PREFIX, RTGETOPT_REQ_STRING }, 953 { "--file-mode-and-mask", RTZIPTARCMD_OPT_FILE_MODE_AND_MASK, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT }, 954 { "--file-mode-or-mask", RTZIPTARCMD_OPT_FILE_MODE_OR_MASK, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT }, 955 { "--dir-mode-and-mask", RTZIPTARCMD_OPT_DIR_MODE_AND_MASK, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT }, 956 { "--dir-mode-or-mask", RTZIPTARCMD_OPT_DIR_MODE_OR_MASK, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_OCT }, 521 957 }; 522 958 … … 528 964 529 965 RTZIPTARCMDOPS Opts; 530 RT_ZERO(Opts); /* nice defaults :-) */ 966 RT_ZERO(Opts); 967 Opts.uidOwner = NIL_RTUID; 968 Opts.gidGroup = NIL_RTUID; 969 Opts.fFileModeAndMask = RTFS_UNIX_ALL_ACCESS_PERMS; 970 Opts.fDirModeAndMask = RTFS_UNIX_ALL_ACCESS_PERMS; 971 #if 0 972 if (RTPermIsSuperUser()) 973 { 974 Opts.fFileModeAndMask = RTFS_UNIX_ALL_PERMS; 975 Opts.fDirModeAndMask = RTFS_UNIX_ALL_PERMS; 976 Opts.fPreserveOwner = true; 977 Opts.fPreserveGroup = true; 978 } 979 #endif 531 980 532 981 RTGETOPTUNION ValueUnion; … … 570 1019 571 1020 case 'p': 572 Opts.fPreservePermissions = true; 1021 Opts.fFileModeAndMask = RTFS_UNIX_ALL_PERMS; 1022 Opts.fDirModeAndMask = RTFS_UNIX_ALL_PERMS; 1023 Opts.fPreserveOwner = true; 1024 Opts.fPreserveGroup = true; 573 1025 break; 574 1026 … … 584 1036 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "You may only specify --owner once"); 585 1037 Opts.pszOwner = ValueUnion.psz; 1038 1039 rc = RTStrToUInt32Full(Opts.pszOwner, 0, &ValueUnion.u32); 1040 if (RT_SUCCESS(rc) && rc != VINF_SUCCESS) 1041 return RTMsgErrorExit(RTEXITCODE_SYNTAX, 1042 "Error convering --owner '%s' into a number: %Rrc", Opts.pszOwner, rc); 1043 if (RT_SUCCESS(rc)) 1044 { 1045 Opts.uidOwner = ValueUnion.u32; 1046 Opts.pszOwner = NULL; 1047 } 586 1048 break; 587 1049 … … 590 1052 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "You may only specify --group once"); 591 1053 Opts.pszGroup = ValueUnion.psz; 1054 1055 rc = RTStrToUInt32Full(Opts.pszGroup, 0, &ValueUnion.u32); 1056 if (RT_SUCCESS(rc) && rc != VINF_SUCCESS) 1057 return RTMsgErrorExit(RTEXITCODE_SYNTAX, 1058 "Error convering --group '%s' into a number: %Rrc", Opts.pszGroup, rc); 1059 if (RT_SUCCESS(rc)) 1060 { 1061 Opts.gidGroup = ValueUnion.u32; 1062 Opts.pszGroup = NULL; 1063 } 592 1064 break; 593 1065 … … 603 1075 break; 604 1076 1077 case RTZIPTARCMD_OPT_FILE_MODE_AND_MASK: 1078 Opts.fFileModeAndMask = ValueUnion.u32 & RTFS_UNIX_ALL_PERMS; 1079 break; 1080 1081 case RTZIPTARCMD_OPT_FILE_MODE_OR_MASK: 1082 Opts.fFileModeOrMask = ValueUnion.u32 & RTFS_UNIX_ALL_PERMS; 1083 break; 1084 1085 case RTZIPTARCMD_OPT_DIR_MODE_AND_MASK: 1086 Opts.fDirModeAndMask = ValueUnion.u32 & RTFS_UNIX_ALL_PERMS; 1087 break; 1088 1089 case RTZIPTARCMD_OPT_DIR_MODE_OR_MASK: 1090 Opts.fDirModeOrMask = ValueUnion.u32 & RTFS_UNIX_ALL_PERMS; 1091 break; 1092 1093 1094 /* Standard bits. */ 605 1095 case 'h': 606 RTPrintf("Usage: to be written\nOption dump:\n"); 607 for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++) 608 if (RT_C_IS_PRINT(s_aOptions[i].iShort)) 609 RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong); 610 else 611 RTPrintf(" %s\n", s_aOptions[i].pszLong); 1096 rtZipTarUsage(RTPathFilename(papszArgs[0])); 612 1097 return RTEXITCODE_SUCCESS; 613 1098 … … 652 1137 { 653 1138 case 't': 654 return rtZipTarCmdList(&Opts); 1139 return rtZipTarDoWithMembers(&Opts, rtZipTarCmdListCallback); 1140 1141 case 'x': 1142 return rtZipTarDoWithMembers(&Opts, rtZipTarCmdExtractCallback); 655 1143 656 1144 case 'A': … … 659 1147 case 'r': 660 1148 case 'u': 661 case 'x':662 1149 case RTZIPTARCMD_OPT_DELETE: 663 1150 return RTMsgErrorExit(RTEXITCODE_FAILURE, "The operation %s is not implemented yet", Opts.pszOperation);
Note:
See TracChangeset
for help on using the changeset viewer.