Changeset 84761 in vbox for trunk/src/VBox/Runtime/common/zip
- Timestamp:
- Jun 10, 2020 3:13:58 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/zip/tarcmd.cpp
r84760 r84761 64 64 #define RTZIPTARCMD_OPT_READ_AHEAD 1010 65 65 #define RTZIPTARCMD_OPT_USE_PUSH_FILE 1011 66 #define RTZIPTARCMD_OPT_NO_RECURSION 1012 66 67 67 68 /** File format. */ … … 111 112 /** Use RTVfsFsStrmPushFile instead of RTVfsFsStrmAdd for files. */ 112 113 bool fUsePushFile; 114 /** Whether to handle directories recursively or not. Defaults to \c true. */ 115 bool fRecursive; 113 116 /** The compressor/decompressor method to employ (0, z or j). */ 114 117 char chZipper; … … 153 156 typedef RTZIPTARCMDOPS *PRTZIPTARCMDOPS; 154 157 158 /** The size of the directory entry buffer we're using. */ 159 #define RTZIPTARCMD_DIRENTRY_BUF_SIZE (sizeof(RTDIRENTRYEX) + RTPATH_MAX) 160 155 161 /** 156 162 * Callback used by rtZipTarDoWithMembers … … 184 190 } 185 191 return false; 192 } 193 194 195 /** 196 * Queries information about a VFS object. 197 * 198 * @returns VBox status code. 199 * @param pszSpec VFS object spec to use. 200 * @param paObjInfo Where to store the queried object information. 201 * Must at least provide 3 structs, namely for UNIX, UNIX_OWNER and UNIX_GROUP attributes. 202 * @param cObjInfo Number of objection information structs handed in. 203 */ 204 static int rtZipTarCmdQueryObjInfo(const char *pszSpec, PRTFSOBJINFO paObjInfo, unsigned cObjInfo) 205 { 206 AssertPtrReturn(paObjInfo, VERR_INVALID_POINTER); 207 AssertReturn(cObjInfo >= 3, VERR_INVALID_PARAMETER); 208 209 RTERRINFOSTATIC ErrInfo; 210 uint32_t offError; 211 int rc = RTVfsChainQueryInfo(pszSpec, &paObjInfo[0], RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK, 212 &offError, RTErrInfoInitStatic(&ErrInfo)); 213 if (RT_SUCCESS(rc)) 214 { 215 rc = RTVfsChainQueryInfo(pszSpec, &paObjInfo[1], RTFSOBJATTRADD_UNIX_OWNER, RTPATH_F_ON_LINK, 216 &offError, RTErrInfoInitStatic(&ErrInfo)); 217 if (RT_SUCCESS(rc)) 218 { 219 rc = RTVfsChainQueryInfo(pszSpec, &paObjInfo[2], RTFSOBJATTRADD_UNIX_GROUP, RTPATH_F_ON_LINK, 220 &offError, RTErrInfoInitStatic(&ErrInfo)); 221 if (RT_FAILURE(rc)) 222 RT_BZERO(&paObjInfo[2], sizeof(RTFSOBJINFO)); 223 } 224 else 225 { 226 RT_BZERO(&paObjInfo[1], sizeof(RTFSOBJINFO)); 227 RT_BZERO(&paObjInfo[2], sizeof(RTFSOBJINFO)); 228 } 229 230 rc = VINF_SUCCESS; /* aObjInfo[1] + aObjInfo[2] are optional. */ 231 } 232 else 233 RTVfsChainMsgError("RTVfsChainQueryInfo", pszSpec, rc, offError, &ErrInfo.Core); 234 235 return rc; 186 236 } 187 237 … … 254 304 255 305 /** 256 * Archives a directory recursively . 306 * Sub-directory helper for creating archives. 307 * 308 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + printed message. 309 * @param pOpts The options. 310 * @param hVfsFss The TAR filesystem stream handle. 311 * @param pszSrc The directory path or VFS spec. We append to the 312 * buffer as we decend. 313 * @param cchSrc The length of the input. 314 * @param paObjInfo[3] Array of three FS object info structures. The first 315 * one is always filled with RTFSOBJATTRADD_UNIX info. 316 * The next two may contain owner and group names if 317 * available. The three buffers can be reused. 318 * @param pszDst The name to archive it the under. We append to the 319 * buffer as we decend. 320 * @param cchDst The length of the input. 321 * @param pDirEntry Directory entry to use for the directory to handle. 322 * @param pErrInfo Error info buffer (saves stack space). 323 */ 324 static RTEXITCODE rtZipTarCmdArchiveDirSub(PRTZIPTARCMDOPS pOpts, RTVFSFSSTREAM hVfsFss, 325 char *pszSrc, size_t cchSrc, RTFSOBJINFO paObjInfo[3], 326 char pszDst[RTPATH_MAX], size_t cchDst, PRTDIRENTRYEX pDirEntry, 327 PRTERRINFOSTATIC pErrInfo) 328 { 329 if (pOpts->fVerbose) 330 RTPrintf("%s\n", pszDst); 331 332 uint32_t offError; 333 RTVFSDIR hVfsIoDir; 334 int rc = RTVfsChainOpenDir(pszSrc, 0 /*fFlags*/, 335 &hVfsIoDir, &offError, RTErrInfoInitStatic(pErrInfo)); 336 if (RT_FAILURE(rc)) 337 return RTVfsChainMsgErrorExitFailure("RTVfsChainOpenDir", pszSrc, rc, offError, &pErrInfo->Core); 338 339 /* Make sure we've got some room in the path, to save us extra work further down. */ 340 if (cchSrc + 3 >= RTPATH_MAX) 341 return RTMsgErrorExitFailure("Source path too long: '%s'\n", pszSrc); 342 343 /* Ensure we've got a trailing slash (there is space for it see above). */ 344 if (!RTPATH_IS_SEP(pszSrc[cchSrc - 1])) 345 { 346 pszSrc[cchSrc++] = RTPATH_SLASH; 347 pszSrc[cchSrc] = '\0'; 348 } 349 350 /* Ditto for destination. */ 351 if (cchDst + 3 >= RTPATH_MAX) 352 return RTMsgErrorExitFailure("Destination path too long: '%s'\n", pszDst); 353 354 if (!RTPATH_IS_SEP(pszDst[cchDst - 1])) 355 { 356 pszDst[cchDst++] = RTPATH_SLASH; 357 pszDst[cchDst] = '\0'; 358 } 359 360 /* 361 * Process the files and subdirs. 362 */ 363 for (;;) 364 { 365 size_t cbDirEntry = RTZIPTARCMD_DIRENTRY_BUF_SIZE; 366 rc = RTVfsDirReadEx(hVfsIoDir, pDirEntry, &cbDirEntry, RTFSOBJATTRADD_UNIX); 367 if (RT_FAILURE(rc)) 368 break; 369 370 /* Check length. */ 371 if (pDirEntry->cbName + cchSrc + 3 >= RTPATH_MAX) 372 { 373 rc = VERR_BUFFER_OVERFLOW; 374 break; 375 } 376 377 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK) 378 { 379 case RTFS_TYPE_DIRECTORY: 380 { 381 if (RTDirEntryExIsStdDotLink(pDirEntry)) 382 continue; 383 384 if (!pOpts->fRecursive) 385 continue; 386 387 memcpy(&pszSrc[cchSrc], pDirEntry->szName, pDirEntry->cbName + 1); 388 if (RT_SUCCESS(rc)) 389 { 390 memcpy(&pszDst[cchDst], pDirEntry->szName, pDirEntry->cbName + 1); 391 rc = rtZipTarCmdArchiveDirSub(pOpts, hVfsFss, pszSrc, cchSrc + pDirEntry->cbName, paObjInfo, 392 pszDst, cchDst + pDirEntry->cbName, pDirEntry, pErrInfo); 393 } 394 395 break; 396 } 397 398 case RTFS_TYPE_FILE: 399 { 400 memcpy(&pszSrc[cchSrc], pDirEntry->szName, pDirEntry->cbName + 1); 401 rc = rtZipTarCmdQueryObjInfo(pszSrc, paObjInfo, 3 /* cObjInfo */); 402 if (RT_SUCCESS(rc)) 403 { 404 memcpy(&pszDst[cchDst], pDirEntry->szName, pDirEntry->cbName + 1); 405 rc = rtZipTarCmdArchiveFile(pOpts, hVfsFss, pszSrc, paObjInfo, pszDst, pErrInfo); 406 } 407 break; 408 } 409 410 default: 411 { 412 if (pOpts->fVerbose) 413 RTPrintf("Warning: File system type %#x for '%s' not implemented yet, sorry! Skipping ...\n", 414 pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK, pDirEntry->szName); 415 break; 416 } 417 } 418 } 419 420 RTVfsDirRelease(hVfsIoDir); 421 422 if (rc != VERR_NO_MORE_FILES) 423 return RTMsgErrorExitFailure("RTVfsDirReadEx failed unexpectedly!"); 424 425 return RTEXITCODE_SUCCESS; 426 } 427 428 429 /** 430 * Archives a directory recursively. 257 431 * 258 432 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + printed message. … … 275 449 PRTERRINFOSTATIC pErrInfo) 276 450 { 277 RT_NOREF(pOpts, hVfsFss, pszSrc, cchSrc, paObjInfo, pszDst, cchDst, pErrInfo); 278 return RTMsgErrorExitFailure("Adding directories has not yet been implemented! Sorry."); 451 RT_NOREF(cchSrc); 452 453 char szSrcAbs[RTPATH_MAX]; 454 int rc = RTPathAbs(pszSrc, szSrcAbs, sizeof(szSrcAbs)); 455 if (RT_FAILURE(rc)) 456 return RTMsgErrorExitFailure("RTPathAbs failed on '%s': %Rrc\n", pszSrc, rc); 457 458 union 459 { 460 uint8_t abPadding[RTZIPTARCMD_DIRENTRY_BUF_SIZE]; 461 RTDIRENTRYEX DirEntry; 462 } uBuf; 463 464 return rtZipTarCmdArchiveDirSub(pOpts, hVfsFss, szSrcAbs, strlen(szSrcAbs), paObjInfo, pszDst, cchDst, &uBuf.DirEntry, pErrInfo); 279 465 } 280 281 466 282 467 … … 491 676 * What kind of object is this and what affiliations does it have? 492 677 */ 493 RTERRINFOSTATIC ErrInfo; 494 uint32_t offError; 495 RTFSOBJINFO aObjInfo[3]; 496 rc = RTVfsChainQueryInfo(szSrc, &aObjInfo[0], RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK, 497 &offError, RTErrInfoInitStatic(&ErrInfo)); 678 RTFSOBJINFO aObjInfo[3]; 679 rc = rtZipTarCmdQueryObjInfo(szSrc, aObjInfo, RT_ELEMENTS(aObjInfo)); 498 680 if (RT_SUCCESS(rc)) 499 681 { 500 501 rc = RTVfsChainQueryInfo(szSrc, &aObjInfo[1], RTFSOBJATTRADD_UNIX_OWNER, RTPATH_F_ON_LINK, 502 &offError, RTErrInfoInitStatic(&ErrInfo)); 503 if (RT_SUCCESS(rc)) 504 { 505 rc = RTVfsChainQueryInfo(szSrc, &aObjInfo[2], RTFSOBJATTRADD_UNIX_GROUP, RTPATH_F_ON_LINK, 506 &offError, RTErrInfoInitStatic(&ErrInfo)); 507 if (RT_FAILURE(rc)) 508 RT_ZERO(aObjInfo[2]); 509 } 510 else 511 { 512 RT_ZERO(aObjInfo[1]); 513 RT_ZERO(aObjInfo[2]); 514 } 682 RTERRINFOSTATIC ErrInfo; 515 683 516 684 /* … … 539 707 } 540 708 else 541 rcExit = RT VfsChainMsgErrorExitFailure("RTVfsChainQueryInfo", pszFile, rc, offError, &ErrInfo.Core);709 rcExit = RTMsgErrorExitFailure("querying object information for '%s' failed (%s)", szSrc, pszFile); 542 710 } 543 711 else … … 1506 1674 { "--sparse", 'S', RTGETOPT_REQ_NOTHING }, 1507 1675 { "--format", RTZIPTARCMD_OPT_FORMAT, RTGETOPT_REQ_STRING }, 1676 { "--no-recursion", RTZIPTARCMD_OPT_NO_RECURSION, RTGETOPT_REQ_NOTHING }, 1508 1677 1509 1678 /* IPRT extensions */ … … 1540 1709 #endif 1541 1710 Opts.enmTarFormat = RTZIPTARFORMAT_DEFAULT; 1711 Opts.fRecursive = true; /* Recursion is implicit unless otherwise specified. */ 1542 1712 1543 1713 RTGETOPTUNION ValueUnion; … … 1628 1798 case RTZIPTARCMD_OPT_UTC: 1629 1799 Opts.fDisplayUtc = true; 1800 break; 1801 1802 case RTZIPTARCMD_OPT_NO_RECURSION: 1803 Opts.fRecursive = false; 1630 1804 break; 1631 1805
Note:
See TracChangeset
for help on using the changeset viewer.