Changeset 34179 in vbox for trunk/src/VBox/Runtime/common/zip
- Timestamp:
- Nov 18, 2010 3:49:17 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 67908
- Location:
- trunk/src/VBox/Runtime/common/zip
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/zip/tar.h
r34060 r34179 48 48 49 49 #define RTZIPTAR_TF_GNU_DUMPDIR 'D' 50 #define RTZIPTAR_TF_GNU_LONGLINK 'K' 51 #define RTZIPTAR_TF_GNU_LONGNAME 'L' 50 #define RTZIPTAR_TF_GNU_LONGLINK 'K' /**< GNU long link header. */ 51 #define RTZIPTAR_TF_GNU_LONGNAME 'L' /**< GNU long name header. */ 52 52 #define RTZIPTAR_TF_GNU_MULTIVOL 'M' 53 53 #define RTZIPTAR_TF_GNU_SPARSE 'S' 54 54 #define RTZIPTAR_TF_GNU_VOLDHR 'V' 55 55 /** @} */ 56 57 58 /** 59 * The ancient tar header. 60 * 61 * The posix and gnu headers are compatible with the members up to and including 62 * link name, from there on they differ. 63 */ 64 typedef struct RTZIPTARHDRANCIENT 65 { 66 char name[100]; 67 char mode[8]; 68 char uid[8]; 69 char gid[8]; 70 char size[12]; 71 char mtime[12]; 72 char chksum[8]; 73 char typeflag; 74 char linkname[100]; /**< Was called linkflag. */ 75 char unused[8+64+16+155+12]; 76 } RTZIPTARHDRANCIENT; 77 AssertCompileSize(RTZIPTARHDRANCIENT, 512); 78 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, name, 0); 79 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, mode, 100); 80 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, uid, 108); 81 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, gid, 116); 82 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, size, 124); 83 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, mtime, 136); 84 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, chksum, 148); 85 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, typeflag, 156); 86 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, linkname, 157); 87 AssertCompileMemberOffset(RTZIPTARHDRANCIENT, unused, 257); 88 56 89 57 90 /** The uniform standard tape archive format magic value. */ … … 164 197 165 198 /** 199 * The bits common to posix and GNU. 200 */ 201 typedef struct RTZIPTARHDRCOMMON 202 { 203 char name[100]; 204 char mode[8]; 205 char uid[8]; 206 char gid[8]; 207 char size[12]; 208 char mtime[12]; 209 char chksum[8]; 210 char typeflag; 211 char linkname[100]; 212 char magic[6]; 213 char version[2]; 214 char uname[32]; 215 char gname[32]; 216 char devmajor[8]; 217 char devminor[8]; 218 char not_common[155+12]; 219 } RTZIPTARHDRCOMMON; 220 221 222 /** 166 223 * Tar header union. 167 224 */ … … 170 227 /** Byte view. */ 171 228 char ab[512]; 229 /** The standard header. */ 230 RTZIPTARHDRANCIENT Ancient; 172 231 /** The standard header. */ 173 232 RTZIPTARHDRPOSIX Posix; 174 233 /** The GNU header. */ 175 234 RTZIPTARHDRGNU Gnu; 235 /** The bits common to both GNU and the standard header. */ 236 RTZIPTARHDRCOMMON Common; 176 237 } RTZIPTARHDR; 177 238 AssertCompileSize(RTZIPTARHDR, 512); -
trunk/src/VBox/Runtime/common/zip/tarcmd.cpp
r34055 r34179 268 268 } 269 269 270 const char *pszLinkType = NULL; 270 271 char szTarget[RTPATH_MAX]; 271 272 szTarget[0] = '\0'; 272 if (RTFS_IS_SYMLINK(UnixInfo.Attr.fMode)) 273 { 274 RTVFSSYMLINK hVfsSymlink = RTVfsObjToSymlink(hVfsObj); 275 if (hVfsSymlink != NIL_RTVFSSYMLINK) 276 { 277 rc = RTVfsSymlinkRead(hVfsSymlink, szTarget, sizeof(szTarget)); 278 if (RT_FAILURE(rc)) 279 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsSymlinkRead returned %Rrc on '%s'", rc, pszName); 280 RTVfsSymlinkRelease(hVfsSymlink); 281 } 282 else 283 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to get symlink object for '%s'", pszName); 284 } 273 RTVFSSYMLINK hVfsSymlink = RTVfsObjToSymlink(hVfsObj); 274 if (hVfsSymlink != NIL_RTVFSSYMLINK) 275 { 276 rc = RTVfsSymlinkRead(hVfsSymlink, szTarget, sizeof(szTarget)); 277 if (RT_FAILURE(rc)) 278 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTVfsSymlinkRead returned %Rrc on '%s'", rc, pszName); 279 RTVfsSymlinkRelease(hVfsSymlink); 280 pszLinkType = RTFS_IS_SYMLINK(UnixInfo.Attr.fMode) ? "->" : "link to"; 281 } 282 else if (RTFS_IS_SYMLINK(UnixInfo.Attr.fMode)) 283 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to get symlink object for '%s'", pszName); 285 284 286 285 /* … … 300 299 default: szMode[0] = '?'; break; 301 300 } 301 if (pszLinkType && szMode[0] != 's') 302 szMode[0] = 'h'; 302 303 303 304 szMode[1] = UnixInfo.Attr.fMode & RTFS_UNIX_IRUSR ? 'r' : '-'; … … 370 371 * Go to press. 371 372 */ 372 if ( RTFS_IS_SYMLINK(UnixInfo.Attr.fMode))373 RTPrintf("%s %s/%s%*s %s %s %s ->%s\n",373 if (pszLinkType) 374 RTPrintf("%s %s/%s%*s %s %s %s %s %s\n", 374 375 szMode, 375 376 Owner.Attr.u.UnixOwner.szName, Group.Attr.u.UnixGroup.szName, … … 378 379 szModTime, 379 380 pszName, 381 pszLinkType, 380 382 szTarget); 381 383 else -
trunk/src/VBox/Runtime/common/zip/tarvfs.cpp
r34060 r34179 34 34 #include <iprt/asm.h> 35 35 #include <iprt/assert.h> 36 #include <iprt/ctype.h> 36 37 #include <iprt/err.h> 37 38 #include <iprt/poll.h> … … 48 49 *******************************************************************************/ 49 50 /** 51 * TAR reader state machine states. 52 */ 53 typedef enum RTZIPTARREADERSTATE 54 { 55 /** Invalid state. */ 56 RTZIPTARREADERSTATE_INVALID = 0, 57 /** Expecting the next file/dir/whatever entry. */ 58 RTZIPTARREADERSTATE_FIRST, 59 /** Expecting more zero headers or the end of the stream. */ 60 RTZIPTARREADERSTATE_ZERO, 61 /** Expecting a GNU long name. */ 62 RTZIPTARREADERSTATE_GNU_LONGNAME, 63 /** Expecting a GNU long link. */ 64 RTZIPTARREADERSTATE_GNU_LONGLINK, 65 /** Expecting a normal header or another GNU specific one. */ 66 RTZIPTARREADERSTATE_GNU_NEXT, 67 /** End of valid states (not included). */ 68 RTZIPTARREADERSTATE_END 69 } RTZIPTARREADERSTATE; 70 71 /** 72 * Tar reader instance data. 73 */ 74 typedef struct RTZIPTARREADER 75 { 76 /** Zero header counter. */ 77 uint32_t cZeroHdrs; 78 /** The state machine state. */ 79 RTZIPTARREADERSTATE enmState; 80 /** The type of the previous TAR header. */ 81 RTZIPTARTYPE enmPrevType; 82 /** The type of the current TAR header. */ 83 RTZIPTARTYPE enmType; 84 /** The current header. */ 85 RTZIPTARHDR Hdr; 86 /** The expected long name/link length (GNU). */ 87 uint32_t cbGnuLongExpect; 88 /** The current long name/link length (GNU). */ 89 uint32_t offGnuLongCur; 90 /** The name of the current object. 91 * This is for handling GNU and PAX long names. */ 92 char szName[RTPATH_MAX]; 93 /** The current link target if symlink or hardlink. */ 94 char szTarget[RTPATH_MAX]; 95 } RTZIPTARREADER; 96 /** Pointer to the TAR reader instance data. */ 97 typedef RTZIPTARREADER *PRTZIPTARREADER; 98 99 /** 50 100 * Tar directory, character device, block device, fifo socket or symbolic link. 51 101 */ … … 53 103 { 54 104 /** The stream offset of the (first) header. */ 55 RTFOFF offHdr; 56 /** The tar header. */ 57 RTZIPTARHDR Hdr; 105 RTFOFF offHdr; 106 /** Pointer to the reader instance data (resides in the filesystem 107 * stream). 108 * @todo Fix this so it won't go stale... Back ref from this obj to fss? */ 109 PRTZIPTARREADER pTarReader; 58 110 /** The object info with unix attributes. */ 59 RTFSOBJINFO ObjInfo;111 RTFSOBJINFO ObjInfo; 60 112 } RTZIPTARBASEOBJ; 61 /** Pointer to a tarfilesystem stream base object. */113 /** Pointer to a TAR filesystem stream base object. */ 62 114 typedef RTZIPTARBASEOBJ *PRTZIPTARBASEOBJ; 63 115 … … 68 120 typedef struct RTZIPTARIOSTREAM 69 121 { 70 /** The basic tarobject data. */71 RTZIPTARBASEOBJ BaseObj;122 /** The basic TAR object data. */ 123 RTZIPTARBASEOBJ BaseObj; 72 124 /** The number of bytes in the file. */ 73 RTFOFF cbFile;125 RTFOFF cbFile; 74 126 /** The current file position. */ 75 RTFOFF offFile;127 RTFOFF offFile; 76 128 /** The number of padding bytes following the file. */ 77 uint32_t cbPadding;129 uint32_t cbPadding; 78 130 /** Set if we've reached the end of the file. */ 79 bool fEndOfStream;131 bool fEndOfStream; 80 132 /** The input I/O stream. */ 81 RTVFSIOSTREAM hVfsIos;133 RTVFSIOSTREAM hVfsIos; 82 134 } RTZIPTARIOSTREAM; 83 /** Pointer to a the private data of a tarfile I/O stream. */135 /** Pointer to a the private data of a TAR file I/O stream. */ 84 136 typedef RTZIPTARIOSTREAM *PRTZIPTARIOSTREAM; 85 137 … … 91 143 { 92 144 /** The input I/O stream. */ 93 RTVFSIOSTREAM hVfsIos;145 RTVFSIOSTREAM hVfsIos; 94 146 95 147 /** The current object (referenced). */ 96 RTVFSOBJ hVfsCurObj;148 RTVFSOBJ hVfsCurObj; 97 149 /** Pointer to the private data if hVfsCurObj is representing a file. */ 98 PRTZIPTARIOSTREAM pCurIosData;150 PRTZIPTARIOSTREAM pCurIosData; 99 151 100 152 /** The start offset. */ 101 RTFOFF offStart;153 RTFOFF offStart; 102 154 /** The offset of the next header. */ 103 RTFOFF offNextHdr;155 RTFOFF offNextHdr; 104 156 105 157 /** Set if we've reached the end of the stream. */ 106 bool fEndOfStream;158 bool fEndOfStream; 107 159 /** Set if we've encountered a fatal error. */ 108 int rcFatal; 160 int rcFatal; 161 162 /** The TAR reader instance data. */ 163 RTZIPTARREADER TarReader; 109 164 } RTZIPTARFSSTREAM; 110 /** Pointer to a the private data of a tarfilesystem stream. */165 /** Pointer to a the private data of a TAR filesystem stream. */ 111 166 typedef RTZIPTARFSSTREAM *PRTZIPTARFSSTREAM; 112 167 113 114 /**115 * Checks if the TAR header is in the ustar format.116 *117 * @returns true / false.118 * @param pTar The TAR header.119 */120 DECLINLINE(bool) rtZipTarHdrIsUstar(PCRTZIPTARHDR pTar)121 {122 return pTar->Posix.magic[0] == 'u'123 && pTar->Posix.magic[1] == 's'124 && pTar->Posix.magic[2] == 't'125 && pTar->Posix.magic[3] == 'a'126 && pTar->Posix.magic[4] == 'r'127 && pTar->Posix.magic[5] == '\0'128 && pTar->Posix.version[0] == '0'129 && pTar->Posix.version[1] == '0';130 }131 132 133 /**134 * Checks if the TAR header is in the ustar format and has a regular file type.135 *136 * @returns true / false.137 * @param pTar The TAR header.138 */139 DECLINLINE(bool) rtZipTarHdrIsRegularUstar(PCRTZIPTARHDR pTar)140 {141 return rtZipTarHdrIsUstar(pTar)142 && ( ( pTar->Posix.typeflag >= RTZIPTAR_TF_NORMAL143 && pTar->Posix.typeflag <= RTZIPTAR_TF_CONTIG)144 || pTar->Posix.typeflag == RTZIPTAR_TF_OLDNORMAL);145 }146 147 148 /**149 * Checks if the TAR header includes a posix user name field.150 *151 * @returns true / false.152 * @param pTar The TAR header.153 */154 DECLINLINE(bool) rtZipTarHdrHasPosixUserName(PCRTZIPTARHDR pTar)155 {156 return pTar->Posix.uname[0] != '\0'157 && rtZipTarHdrIsUstar(pTar);158 }159 160 161 /**162 * Checks if the TAR header includes a posix group name field.163 *164 * @returns true / false.165 * @param pTar The TAR header.166 */167 DECLINLINE(bool) rtZipTarHdrHasPosixGroupName(PCRTZIPTARHDR pTar)168 {169 return pTar->Posix.gname[0] != '\0'170 && rtZipTarHdrIsUstar(pTar);171 }172 173 174 /**175 * Checks if the TAR header includes a posix compatible path prefix field.176 *177 * @returns true / false.178 * @param pTar The TAR header.179 */180 DECLINLINE(bool) rtZipTarHdrHasPrefix(PCRTZIPTARHDR pTar)181 {182 return pTar->Posix.prefix[0] != '\0'183 && rtZipTarHdrIsUstar(pTar);184 }185 168 186 169 … … 202 185 { 203 186 /* 204 * Skip leading zeros, savinga few slower loops below.187 * Skip leading spaces. Include zeros to save a few slower loops below. 205 188 */ 206 while (cchField > 0 && *pszField == '0') 189 char ch; 190 while (cchField > 0 && ((ch = *pszField) == ' '|| ch == '0')) 207 191 cchField--, pszField++; 208 192 … … 229 213 while (cchField > 0) 230 214 { 231 ch ar ch= *pszField++;215 ch = *pszField++; 232 216 if (ch != 0 && ch != ' ') 233 217 return cchField < cchFieldOrg … … 248 232 249 233 /** 250 * Calculates the tarheader checksums and detects if it's all zeros.234 * Calculates the TAR header checksums and detects if it's all zeros. 251 235 * 252 236 * @returns true if all zeros, false if not. … … 283 267 bool const fZeroHdr = i32Unsigned == 0; 284 268 285 pch = pHdr-> Posix.chksum;286 pchEnd = pch + sizeof(pHdr-> Posix.chksum);269 pch = pHdr->Common.chksum; 270 pchEnd = pch + sizeof(pHdr->Common.chksum); 287 271 do 288 272 { … … 291 275 } while (++pch != pchEnd); 292 276 293 i32Unsigned += (unsigned char)' ' * sizeof(pHdr-> Posix.chksum);294 i32Signed += (signed char)' ' * sizeof(pHdr-> Posix.chksum);277 i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum); 278 i32Signed += (signed char)' ' * sizeof(pHdr->Common.chksum); 295 279 296 280 *pi32Unsigned = i32Unsigned; … … 304 288 * Validates the TAR header. 305 289 * 306 * @returns VINF_SUCCESS if valid, appropriate VERR_TAR_XXX if not. 290 * @returns VINF_SUCCESS if valid, VERR_TAR_ZERO_HEADER if all zeros, and 291 * the appropriate VERR_TAR_XXX otherwise. 307 292 * @param pTar The TAR header. 308 293 * @param penmType Where to return the type of header on success. … … 322 307 */ 323 308 int64_t i64HdrChkSum; 324 int rc = rtZipTarHdrFieldToNum(pTar-> Posix.chksum, sizeof(pTar->Posix.chksum), true /*fOctalOnly*/, &i64HdrChkSum);309 int rc = rtZipTarHdrFieldToNum(pTar->Common.chksum, sizeof(pTar->Common.chksum), true /*fOctalOnly*/, &i64HdrChkSum); 325 310 if (RT_FAILURE(rc)) 326 311 return VERR_TAR_BAD_CHKSUM_FIELD; … … 330 315 331 316 /* 332 * Detect the tartype.317 * Detect the TAR type. 333 318 */ 334 319 RTZIPTARTYPE enmType; 335 if ( pTar->Posix.magic[0] == 'u' 336 && pTar->Posix.magic[1] == 's' 337 && pTar->Posix.magic[2] == 't' 338 && pTar->Posix.magic[3] == 'a' 339 && pTar->Posix.magic[4] == 'r') 340 { 341 if ( pTar->Posix.magic[5] == '\0' 342 && pTar->Posix.version[0] == '0' 343 && pTar->Posix.version[1] == '0') 320 if ( pTar->Common.magic[0] == 'u' 321 && pTar->Common.magic[1] == 's' 322 && pTar->Common.magic[2] == 't' 323 && pTar->Common.magic[3] == 'a' 324 && pTar->Common.magic[4] == 'r') 325 { 326 /** @todo detect star headers */ 327 if ( pTar->Common.magic[5] == '\0' 328 && pTar->Common.version[0] == '0' 329 && pTar->Common.version[1] == '0') 344 330 enmType = RTZIPTARTYPE_POSIX; 345 else if ( pTar-> Posix.magic[5] == ' '346 && pTar-> Posix.version[0] == ' '347 && pTar-> Posix.version[1] == '\0')331 else if ( pTar->Common.magic[5] == ' ' 332 && pTar->Common.version[0] == ' ' 333 && pTar->Common.version[1] == '\0') 348 334 enmType = RTZIPTARTYPE_GNU; 349 335 else … … 357 343 * Perform some basic checks. 358 344 */ 359 /** @todo more/less? */ 360 switch (pTar->Posix.typeflag) 345 switch (enmType) 346 { 347 case RTZIPTARTYPE_POSIX: 348 if ( !RT_C_IS_ALNUM(pTar->Common.typeflag) 349 && !pTar->Common.typeflag == '\0') 350 return VERR_TAR_UNKNOWN_TYPE_FLAG; 351 break; 352 353 case RTZIPTARTYPE_GNU: 354 switch (pTar->Common.typeflag) 355 { 356 case RTZIPTAR_TF_OLDNORMAL: 357 case RTZIPTAR_TF_NORMAL: 358 case RTZIPTAR_TF_CONTIG: 359 case RTZIPTAR_TF_DIR: 360 case RTZIPTAR_TF_CHR: 361 case RTZIPTAR_TF_BLK: 362 case RTZIPTAR_TF_LINK: 363 case RTZIPTAR_TF_SYMLINK: 364 case RTZIPTAR_TF_FIFO: 365 break; 366 367 case RTZIPTAR_TF_GNU_LONGLINK: 368 case RTZIPTAR_TF_GNU_LONGNAME: 369 break; 370 371 case RTZIPTAR_TF_GNU_DUMPDIR: 372 case RTZIPTAR_TF_GNU_MULTIVOL: 373 case RTZIPTAR_TF_GNU_SPARSE: 374 case RTZIPTAR_TF_GNU_VOLDHR: 375 /** @todo Implement full GNU TAR support. .*/ 376 return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE; 377 378 default: 379 return VERR_TAR_UNKNOWN_TYPE_FLAG; 380 } 381 break; 382 383 case RTZIPTARTYPE_ANCIENT: 384 switch (pTar->Common.typeflag) 385 { 386 case RTZIPTAR_TF_OLDNORMAL: 387 case RTZIPTAR_TF_NORMAL: 388 case RTZIPTAR_TF_CONTIG: 389 case RTZIPTAR_TF_DIR: 390 case RTZIPTAR_TF_LINK: 391 case RTZIPTAR_TF_SYMLINK: 392 case RTZIPTAR_TF_FIFO: 393 break; 394 default: 395 return VERR_TAR_UNKNOWN_TYPE_FLAG; 396 } 397 break; 398 default: /* shut up gcc */ 399 AssertFailedReturn(VERR_INTERNAL_ERROR_3); 400 } 401 402 return VINF_SUCCESS; 403 } 404 405 406 /** 407 * Parses and validates the first TAR header of a archive/file/dir/whatever. 408 * 409 * @returns IPRT status code. 410 * @param pThis The TAR reader stat. 411 * @param pTar The TAR header that has been read. 412 * @param fFirst Set if this is the first header, otherwise 413 * clear. 414 */ 415 static int rtZipTarReaderParseNextHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr, bool fFirst) 416 { 417 int rc; 418 419 /* 420 * Basic header validation and detection first. 421 */ 422 RTZIPTARTYPE enmType; 423 rc = rtZipTarHdrValidate(pHdr, &enmType); 424 if (RT_FAILURE_NP(rc)) 425 { 426 if (rc == VERR_TAR_ZERO_HEADER) 427 { 428 pThis->cZeroHdrs = 1; 429 pThis->enmState = RTZIPTARREADERSTATE_ZERO; 430 return VINF_SUCCESS; 431 } 432 return rc; 433 } 434 if (fFirst) 435 pThis->enmType = enmType; 436 437 /* 438 * Handle the header by type. 439 */ 440 switch (pHdr->Common.typeflag) 361 441 { 362 442 case RTZIPTAR_TF_OLDNORMAL: … … 368 448 case RTZIPTAR_TF_BLK: 369 449 case RTZIPTAR_TF_FIFO: 370 { 371 if (!pTar->Posix.name[0]) 450 case RTZIPTAR_TF_DIR: 451 /* 452 * Extract the name first. 453 */ 454 if (!pHdr->Common.name[0]) 372 455 return VERR_TAR_EMPTY_NAME; 373 374 /** @todo People claim some (older and newer buggy) tar stores dirs as regular files with a trailing slash. */ 375 const char *pchEnd = RTStrEnd(&pTar->Posix.name[0], sizeof(pTar->Posix.name)); 376 pchEnd = pchEnd ? pchEnd - 1 : &pTar->Posix.name[sizeof(pTar->Posix.name) - 1]; 377 if (*pchEnd == '/') 378 return VERR_TAR_NON_DIR_ENDS_WITH_SLASH; 379 break; 380 } 381 382 case RTZIPTAR_TF_DIR: 383 if (!pTar->Posix.name[0]) 384 return VERR_TAR_EMPTY_NAME; 456 if (pThis->enmType == RTZIPTARTYPE_POSIX) 457 { 458 Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0'); 459 pThis->szName[0] = '\0'; 460 if (pHdr->Posix.prefix[0]) 461 { 462 rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Posix.prefix, sizeof(pHdr->Posix.prefix)); 463 AssertRC(rc); /* shall not fail */ 464 rc = RTStrCat(pThis->szName, sizeof(pThis->szName), "/"); 465 AssertRC(rc); /* ditto */ 466 } 467 rc = RTStrCatEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); 468 AssertRCReturn(rc, rc); 469 } 470 else if (pThis->enmType == RTZIPTARTYPE_GNU) 471 { 472 if (!pThis->szName[0]) 473 { 474 rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); 475 AssertRCReturn(rc, rc); 476 } 477 } 478 else 479 { 480 /* Old TAR */ 481 Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0'); 482 rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); 483 AssertRCReturn(rc, rc); 484 } 485 486 /* 487 * Extract the link target. 488 */ 489 if ( pHdr->Common.typeflag == RTZIPTAR_TF_LINK 490 || pHdr->Common.typeflag == RTZIPTAR_TF_SYMLINK) 491 { 492 if ( pThis->enmType == RTZIPTARTYPE_POSIX 493 || pThis->enmType == RTZIPTARTYPE_ANCIENT 494 || (pThis->enmType == RTZIPTARTYPE_GNU && pThis->szTarget[0] == '\0') 495 ) 496 { 497 Assert(pThis->szTarget[0] == '\0'); 498 rc = RTStrCopyEx(pThis->szTarget, sizeof(pThis->szTarget), 499 pHdr->Common.linkname, sizeof(pHdr->Common.linkname)); 500 AssertRCReturn(rc, rc); 501 } 502 } 503 else 504 pThis->szTarget[0] = '\0'; 505 506 pThis->Hdr = *pHdr; 385 507 break; 386 508 387 509 case RTZIPTAR_TF_X_HDR: 388 510 case RTZIPTAR_TF_X_GLOBAL: 511 /** @todo implement PAX */ 389 512 return VERR_TAR_UNSUPPORTED_PAX_TYPE; 390 513 391 514 case RTZIPTAR_TF_SOLARIS_XHDR: 515 /** @todo implement solaris / pax attribute lists. */ 392 516 return VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE; 393 517 518 519 /* 520 * A GNU long name or long link is a dummy record followed by one or 521 * more 512 byte string blocks holding the long name/link. The name 522 * lenght is encoded in the size field, null terminator included. If 523 * it is a symlink or hard link the long name may be followed by a 524 * long link sequence. 525 */ 526 case RTZIPTAR_TF_GNU_LONGNAME: 527 case RTZIPTAR_TF_GNU_LONGLINK: 528 { 529 if (strcmp(pHdr->Gnu.name, "././@LongLink")) 530 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 531 532 int64_t cch64; 533 rc = rtZipTarHdrFieldToNum(pHdr->Gnu.size, sizeof(pHdr->Gnu.size), false /*fOctalOnly*/, &cch64); 534 if (RT_FAILURE(rc) || cch64 < 0 || cch64 > _1M) 535 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 536 if (cch64 >= sizeof(pThis->szName)) 537 return VERR_TAR_NAME_TOO_LONG; 538 539 pThis->cbGnuLongExpect = (uint32_t)cch64; 540 pThis->offGnuLongCur = 0; 541 pThis->enmState = pHdr->Common.typeflag == RTZIPTAR_TF_GNU_LONGNAME 542 ? RTZIPTARREADERSTATE_GNU_LONGNAME 543 : RTZIPTARREADERSTATE_GNU_LONGLINK; 544 break; 545 } 546 394 547 case RTZIPTAR_TF_GNU_DUMPDIR: 395 case RTZIPTAR_TF_GNU_LONGLINK:396 case RTZIPTAR_TF_GNU_LONGNAME:397 548 case RTZIPTAR_TF_GNU_MULTIVOL: 398 549 case RTZIPTAR_TF_GNU_SPARSE: 399 550 case RTZIPTAR_TF_GNU_VOLDHR: 551 /** @todo Implement or skip GNU headers */ 400 552 return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE; 401 } 402 553 554 default: 555 return VERR_TAR_UNKNOWN_TYPE_FLAG; 556 } 403 557 404 558 return VINF_SUCCESS; 405 559 } 406 560 561 /** 562 * Parses and validates a TAR header. 563 * 564 * @returns IPRT status code. 565 * @param pThis The TAR reader stat. 566 * @param pTar The TAR header that has been read. 567 */ 568 static int rtZipTarReaderParseHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr) 569 { 570 switch (pThis->enmState) 571 { 572 /* 573 * The first record for a file/directory/whatever. 574 */ 575 case RTZIPTARREADERSTATE_FIRST: 576 pThis->Hdr.Common.typeflag = 0x7f; 577 pThis->enmPrevType = pThis->enmType; 578 pThis->enmType = RTZIPTARTYPE_INVALID; 579 pThis->offGnuLongCur = 0; 580 pThis->cbGnuLongExpect = 0; 581 pThis->szName[0] = '\0'; 582 pThis->szTarget[0] = '\0'; 583 return rtZipTarReaderParseNextHeader(pThis, pHdr, true /*fFirst*/); 584 585 /* 586 * There should only be so many zero headers at the end of the file as 587 * it is a function of the block size used when writing. Don't go on 588 * reading them forever in case someone points us to /dev/zero. 589 */ 590 case RTZIPTARREADERSTATE_ZERO: 591 if (ASMMemIsAllU32(pHdr, sizeof(*pHdr), 0) != NULL) 592 return VERR_TAR_ZERO_HEADER; 593 pThis->cZeroHdrs++; 594 if (pThis->cZeroHdrs <= _64K / 512 + 2) 595 return VINF_SUCCESS; 596 return VERR_TAR_ZERO_HEADER; 597 598 case RTZIPTARREADERSTATE_GNU_LONGNAME: 599 case RTZIPTARREADERSTATE_GNU_LONGLINK: 600 { 601 size_t cbIncoming = RTStrNLen((const char *)pHdr->ab, sizeof(*pHdr)); 602 if (cbIncoming < sizeof(*pHdr)) 603 cbIncoming += 1; 604 605 if (cbIncoming + pThis->offGnuLongCur > pThis->cbGnuLongExpect) 606 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 607 if ( cbIncoming < sizeof(*pHdr) 608 && cbIncoming + pThis->offGnuLongCur != pThis->cbGnuLongExpect) 609 return VERR_TAR_MALFORMED_GNU_LONGXXXX; 610 611 char *pszDst = pThis->enmState == RTZIPTARREADERSTATE_GNU_LONGNAME ? pThis->szName : pThis->szTarget; 612 pszDst += pThis->offGnuLongCur; 613 memcpy(pszDst, pHdr->ab, cbIncoming); 614 615 pThis->offGnuLongCur += cbIncoming; 616 if (pThis->offGnuLongCur == pThis->cbGnuLongExpect) 617 pThis->enmState = RTZIPTARREADERSTATE_GNU_NEXT; 618 return VINF_SUCCESS; 619 } 620 621 case RTZIPTARREADERSTATE_GNU_NEXT: 622 pThis->enmState = RTZIPTARREADERSTATE_FIRST; 623 return rtZipTarReaderParseNextHeader(pThis, pHdr, false /*fFirst*/); 624 625 default: 626 return VERR_INTERNAL_ERROR_5; 627 } 628 } 407 629 408 630 /** … … 413 635 * 414 636 * @returns VINF_SUCCESS if valid, appropriate VERR_TAR_XXX if not. 415 * @param pT ar The TAR header (input).637 * @param pThis The TAR reader instance. 416 638 * @param pObjInfo The object info structure (output). 417 639 */ 418 static int rtZipTar HdrToFsObjInfo(PCRTZIPTARHDR pTar, PRTFSOBJINFO pObjInfo)640 static int rtZipTarReaderGetFsObjInfo(PRTZIPTARREADER pThis, PRTFSOBJINFO pObjInfo) 419 641 { 420 642 /* … … 424 646 425 647 /* 426 * Convert the tarfield in RTFSOBJINFO order.648 * Convert the TAR field in RTFSOBJINFO order. 427 649 */ 428 650 int rc; … … 438 660 } while (0) 439 661 440 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pT ar->Posix.size);662 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size); 441 663 pObjInfo->cbAllocated = RT_ALIGN_64(pObjInfo->cbObject, 512); 442 664 int64_t c64SecModTime; 443 GET_TAR_NUMERIC_FIELD_RET(c64SecModTime, pT ar->Posix.mtime);444 RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, 445 RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, 446 RTTimeSpecSetSeconds(&pObjInfo->AccessTime, 447 RTTimeSpecSetSeconds(&pObjInfo->BirthTime, 665 GET_TAR_NUMERIC_FIELD_RET(c64SecModTime, pThis->Hdr.Common.mtime); 666 RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, c64SecModTime); 667 RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, c64SecModTime); 668 RTTimeSpecSetSeconds(&pObjInfo->AccessTime, c64SecModTime); 669 RTTimeSpecSetSeconds(&pObjInfo->BirthTime, c64SecModTime); 448 670 if (c64SecModTime != RTTimeSpecGetSeconds(&pObjInfo->ModificationTime)) 449 671 return VERR_TAR_NUM_VALUE_TOO_LARGE; 450 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pT ar->Posix.mode);672 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pThis->Hdr.Common.mode); 451 673 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX; 452 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pT ar->Posix.uid);453 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pT ar->Posix.gid);674 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pThis->Hdr.Common.uid); 675 GET_TAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pThis->Hdr.Common.gid); 454 676 pObjInfo->Attr.u.Unix.cHardlinks = 1; 455 677 pObjInfo->Attr.u.Unix.INodeIdDevice = 0; … … 458 680 pObjInfo->Attr.u.Unix.GenerationId = 0; 459 681 pObjInfo->Attr.u.Unix.Device = 0; 460 if ( pTar->Posix.typeflag == RTZIPTAR_TF_CHR 461 || pTar->Posix.typeflag == RTZIPTAR_TF_BLK) 462 { 463 uint32_t uMajor, uMinor; 464 GET_TAR_NUMERIC_FIELD_RET(uMajor, pTar->Posix.devmajor); 465 GET_TAR_NUMERIC_FIELD_RET(uMinor, pTar->Posix.devminor); 466 pObjInfo->Attr.u.Unix.Device = RTDEV_MAKE(uMajor, uMinor); 467 if ( uMajor != RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device) 468 || uMinor != RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device)) 469 return VERR_TAR_DEV_VALUE_TOO_LARGE; 682 switch (pThis->enmType) 683 { 684 case RTZIPTARTYPE_POSIX: 685 case RTZIPTARTYPE_GNU: 686 if ( pThis->Hdr.Common.typeflag == RTZIPTAR_TF_CHR 687 || pThis->Hdr.Common.typeflag == RTZIPTAR_TF_BLK) 688 { 689 uint32_t uMajor, uMinor; 690 GET_TAR_NUMERIC_FIELD_RET(uMajor, pThis->Hdr.Common.devmajor); 691 GET_TAR_NUMERIC_FIELD_RET(uMinor, pThis->Hdr.Common.devminor); 692 pObjInfo->Attr.u.Unix.Device = RTDEV_MAKE(uMajor, uMinor); 693 if ( uMajor != RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device) 694 || uMinor != RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device)) 695 return VERR_TAR_DEV_VALUE_TOO_LARGE; 696 } 697 break; 698 699 default: 700 if ( pThis->Hdr.Common.typeflag == RTZIPTAR_TF_CHR 701 || pThis->Hdr.Common.typeflag == RTZIPTAR_TF_BLK) 702 return VERR_TAR_UNKNOWN_TYPE_FLAG; 470 703 } 471 704 … … 476 709 * Also validate some more now that we've got the numbers to work with. 477 710 */ 478 if (pObjInfo->Attr.fMode & ~RTFS_UNIX_MASK) 711 if ( (pObjInfo->Attr.fMode & ~RTFS_UNIX_MASK) 712 && pThis->enmType == RTZIPTARTYPE_POSIX) 479 713 return VERR_TAR_BAD_MODE_FIELD; 714 pObjInfo->Attr.fMode &= RTFS_UNIX_MASK; 480 715 481 716 RTFMODE fModeType = 0; 482 switch (pT ar->Posix.typeflag)717 switch (pThis->Hdr.Common.typeflag) 483 718 { 484 719 case RTZIPTAR_TF_OLDNORMAL: 485 720 case RTZIPTAR_TF_NORMAL: 486 721 case RTZIPTAR_TF_CONTIG: 487 fModeType |= RTFS_TYPE_FILE; 488 break; 722 { 723 const char *pszEnd = strchr(pThis->szName, '\0'); 724 if (pszEnd == &pThis->szName[0] || pszEnd[-1] != '/') 725 fModeType |= RTFS_TYPE_FILE; 726 else 727 fModeType |= RTFS_TYPE_DIRECTORY; 728 break; 729 } 489 730 490 731 case RTZIPTAR_TF_LINK: 491 732 if (pObjInfo->cbObject != 0) 733 #if 0 /* too strict */ 492 734 return VERR_TAR_SIZE_NOT_ZERO; 735 #else 736 pObjInfo->cbObject = pObjInfo->cbAllocated = 0; 737 #endif 493 738 fModeType |= RTFS_TYPE_FILE; /* no better idea for now */ 494 739 break; … … 513 758 fModeType |= RTFS_TYPE_FIFO; 514 759 break; 760 761 case RTZIPTAR_TF_GNU_LONGLINK: 762 case RTZIPTAR_TF_GNU_LONGNAME: 763 /* ASSUMES RTFS_TYPE_XXX uses the same values as GNU stored in the mode field. */ 764 fModeType = pObjInfo->Attr.fMode & RTFS_TYPE_MASK; 765 switch (fModeType) 766 { 767 case RTFS_TYPE_FILE: 768 case RTFS_TYPE_DIRECTORY: 769 case RTFS_TYPE_SYMLINK: 770 case RTFS_TYPE_DEV_BLOCK: 771 case RTFS_TYPE_DEV_CHAR: 772 case RTFS_TYPE_FIFO: 773 break; 774 775 default: 776 case 0: 777 return VERR_TAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */ 778 } 515 779 516 780 default: … … 520 784 && (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) != fModeType) 521 785 return VERR_TAR_MODE_WITH_TYPE; 786 pObjInfo->Attr.fMode &= ~RTFS_TYPE_MASK; 522 787 pObjInfo->Attr.fMode |= fModeType; 523 788 524 switch (pT ar->Posix.typeflag)789 switch (pThis->Hdr.Common.typeflag) 525 790 { 526 791 case RTZIPTAR_TF_CHR: … … 537 802 538 803 804 /** 805 * Checks if the reader is expecting more headers. 806 * 807 * @returns true / false. 808 * @param pThis The TAR reader instance. 809 */ 810 static bool rtZipTarReaderExpectingMoreHeaders(PRTZIPTARREADER pThis) 811 { 812 return pThis->enmState != RTZIPTARREADERSTATE_FIRST; 813 } 814 815 816 /** 817 * Checks if we're at the end of the TAR file. 818 * 819 * @returns true / false. 820 * @param pThis The TAR reader instance. 821 */ 822 static bool rtZipTarReaderIsAtEnd(PRTZIPTARREADER pThis) 823 { 824 if (!pThis->cZeroHdrs) 825 return false; 826 827 /* Here is a kludge to try deal with archivers not putting at least two 828 zero headers at the end. Afraid it may require further relaxing 829 later on, but let's try be strict about things for now. */ 830 return pThis->cZeroHdrs >= (pThis->enmPrevType == RTZIPTARTYPE_POSIX ? 2 : 1); 831 } 832 833 834 /** 835 * Checks if the current TAR object is a hard link or not. 836 * 837 * @returns true if it is, false if not. 838 * @param pThis The TAR reader instance. 839 */ 840 static bool rtZipTarReaderIsHardlink(PRTZIPTARREADER pThis) 841 { 842 return pThis->Hdr.Common.typeflag == RTZIPTAR_TF_LINK; 843 } 844 845 846 /** 847 * Checks if the TAR header includes a POSIX or GNU user name field. 848 * 849 * @returns true / false. 850 * @param pThis The TAR reader instance. 851 */ 852 DECLINLINE(bool) rtZipTarReaderHasUserName(PRTZIPTARREADER pThis) 853 { 854 return pThis->Hdr.Common.uname[0] != '\0' 855 && ( pThis->enmType == RTZIPTARTYPE_POSIX 856 || pThis->enmType == RTZIPTARTYPE_GNU); 857 } 858 859 860 /** 861 * Checks if the TAR header includes a POSIX or GNU group name field. 862 * 863 * @returns true / false. 864 * @param pThis The TAR reader instance. 865 */ 866 DECLINLINE(bool) rtZipTarReaderHasGroupName(PRTZIPTARREADER pThis) 867 { 868 return pThis->Hdr.Common.gname[0] != '\0' 869 && ( pThis->enmType == RTZIPTARTYPE_POSIX 870 || pThis->enmType == RTZIPTARTYPE_GNU); 871 } 872 873 539 874 /* 540 875 * … … 581 916 pObjInfo->Attr.u.UnixOwner.uid = pThis->ObjInfo.Attr.u.Unix.uid; 582 917 pObjInfo->Attr.u.UnixOwner.szName[0] = '\0'; 583 if (rtZipTarHdrHasPosixUserName(&pThis->Hdr)) 584 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), pThis->Hdr.Posix.uname); 918 if (rtZipTarReaderHasUserName(pThis->pTarReader)) 919 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), 920 pThis->pTarReader->Hdr.Common.uname); 585 921 break; 586 922 … … 590 926 pObjInfo->Attr.u.UnixGroup.gid = pThis->ObjInfo.Attr.u.Unix.gid; 591 927 pObjInfo->Attr.u.UnixGroup.szName[0] = '\0'; 592 if (rtZipTarHdrHasPosixGroupName(&pThis->Hdr)) 593 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), pThis->Hdr.Posix.gname); 928 if (rtZipTarReaderHasGroupName(pThis->pTarReader)) 929 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), 930 pThis->pTarReader->Hdr.Common.gname); 594 931 break; 595 932 … … 867 1204 { 868 1205 PRTZIPTARBASEOBJ pThis = (PRTZIPTARBASEOBJ)pvThis; 869 return RTStrCopy(pszTarget, cbTarget, pThis-> Hdr.Posix.linkname);1206 return RTStrCopy(pszTarget, cbTarget, pThis->pTarReader->szTarget); 870 1207 } 871 1208 … … 963 1300 * Make sure the input stream is in the right place. 964 1301 */ 965 RTFOFF off = RTVfsIoStrmTell(pThis->hVfsIos);966 while ( off >= 0967 && off < pThis->offNextHdr)968 { 969 int rc = RTVfsIoStrmSkip(pThis->hVfsIos, pThis->offNextHdr - off );1302 RTFOFF offHdr = RTVfsIoStrmTell(pThis->hVfsIos); 1303 while ( offHdr >= 0 1304 && offHdr < pThis->offNextHdr) 1305 { 1306 int rc = RTVfsIoStrmSkip(pThis->hVfsIos, pThis->offNextHdr - offHdr); 970 1307 if (RT_FAILURE(rc)) 971 1308 { … … 974 1311 } 975 1312 976 off = RTVfsIoStrmTell(pThis->hVfsIos);977 } 978 979 if (off < 0)980 return pThis->rcFatal = (int)off ;981 if (off > pThis->offNextHdr)1313 offHdr = RTVfsIoStrmTell(pThis->hVfsIos); 1314 } 1315 1316 if (offHdr < 0) 1317 return pThis->rcFatal = (int)offHdr; 1318 if (offHdr > pThis->offNextHdr) 982 1319 return pThis->rcFatal = VERR_INTERNAL_ERROR_3; 983 1320 984 1321 /* 985 * Read the next header. 986 */ 987 size_t cbRead; 988 RTZIPTARHDR Hdr; 989 int rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead); 1322 * Consume TAR headers. 1323 */ 1324 size_t cbHdrs = 0; 1325 int rc; 1326 do 1327 { 1328 /* 1329 * Read the next header. 1330 */ 1331 RTZIPTARHDR Hdr; 1332 size_t cbRead; 1333 rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead); 1334 if (RT_FAILURE(rc)) 1335 return pThis->rcFatal = rc; 1336 if (rc == VINF_EOF && cbRead == 0) 1337 { 1338 pThis->fEndOfStream = true; 1339 return rtZipTarReaderIsAtEnd(&pThis->TarReader) ? VERR_EOF : VERR_TAR_UNEXPECTED_EOS; 1340 } 1341 if (cbRead != sizeof(Hdr)) 1342 return pThis->rcFatal = VERR_TAR_UNEXPECTED_EOS; 1343 1344 cbHdrs += sizeof(Hdr); 1345 1346 /* 1347 * Parse the it. 1348 */ 1349 rc = rtZipTarReaderParseHeader(&pThis->TarReader, &Hdr); 1350 if (RT_FAILURE(rc)) 1351 return pThis->rcFatal = rc; 1352 } while (rtZipTarReaderExpectingMoreHeaders(&pThis->TarReader)); 1353 1354 pThis->offNextHdr = offHdr + cbHdrs; 1355 1356 /* 1357 * Fill an object info structure from the current TAR state. 1358 */ 1359 RTFSOBJINFO Info; 1360 rc = rtZipTarReaderGetFsObjInfo(&pThis->TarReader, &Info); 990 1361 if (RT_FAILURE(rc)) 991 1362 return pThis->rcFatal = rc; 992 if (rc == VINF_EOF && cbRead == 0)993 {994 pThis->fEndOfStream = true;995 return VERR_EOF;996 }997 if (cbRead != sizeof(Hdr))998 return pThis->rcFatal = VERR_TAR_UNEXPECTED_EOS;999 1000 pThis->offNextHdr = off + sizeof(Hdr);1001 1002 /*1003 * Validate the header and convert to binary object info.1004 * We pick up the start of the zero headers here in the failure path.1005 */1006 RTZIPTARTYPE enmTarType;1007 rc = rtZipTarHdrValidate(&Hdr, &enmTarType);1008 if (RT_FAILURE_NP(rc))1009 {1010 if (rc == VERR_TAR_ZERO_HEADER)1011 {1012 int rc2 = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead);1013 if (RT_FAILURE(rc2))1014 return pThis->rcFatal = rc2;1015 if (ASMMemIsAllU32(&Hdr, sizeof(Hdr), 0) == NULL)1016 {1017 pThis->fEndOfStream = true;1018 if (RTVfsIoStrmIsAtEnd(pThis->hVfsIos))1019 return VERR_EOF;1020 1021 /* Just drain the stream because blocksize may dictate that1022 there is a whole bunch of stuff comming up. */1023 for (uint32_t i = 0; i < _32K / 512; i++)1024 {1025 rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead);1026 if (rc == VINF_EOF)1027 return VERR_EOF;1028 if (RT_FAILURE(rc))1029 break;1030 Assert(cbRead == sizeof(Hdr));1031 }1032 }1033 }1034 1035 return pThis->rcFatal = rc;1036 }1037 1038 RTFSOBJINFO Info;1039 rc = rtZipTarHdrToFsObjInfo(&Hdr, &Info);1040 if (RT_FAILURE(rc))1041 return pThis->rcFatal = rc;1042 1363 1043 1364 /* … … 1046 1367 RTVFSOBJTYPE enmType; 1047 1368 RTVFSOBJ hVfsObj; 1048 switch (Hdr.Posix.typeflag) 1369 RTFMODE fType = Info.Attr.fMode & RTFS_TYPE_MASK; 1370 if (rtZipTarReaderIsHardlink(&pThis->TarReader)) 1371 fType = RTFS_TYPE_SYMLINK; 1372 switch (fType) 1049 1373 { 1050 1374 /* 1051 1375 * Files are represented by a VFS I/O stream. 1052 1376 */ 1053 case RTZIPTAR_TF_NORMAL: 1054 case RTZIPTAR_TF_OLDNORMAL: 1055 case RTZIPTAR_TF_CONTIG: 1377 case RTFS_TYPE_FILE: 1056 1378 { 1057 1379 RTVFSIOSTREAM hVfsIos; … … 1067 1389 return pThis->rcFatal = rc; 1068 1390 1069 pIosData->BaseObj.offHdr = off;1070 pIosData->BaseObj. Hdr = Hdr;1071 pIosData->BaseObj.ObjInfo = Info;1072 pIosData->cbFile = Info.cbObject;1073 pIosData->offFile = 0;1074 pIosData->cbPadding = Info.cbAllocated - Info.cbObject;1075 pIosData->fEndOfStream = false;1076 pIosData->hVfsIos = pThis->hVfsIos;1391 pIosData->BaseObj.offHdr = offHdr; 1392 pIosData->BaseObj.pTarReader= &pThis->TarReader; 1393 pIosData->BaseObj.ObjInfo = Info; 1394 pIosData->cbFile = Info.cbObject; 1395 pIosData->offFile = 0; 1396 pIosData->cbPadding = Info.cbAllocated - Info.cbObject; 1397 pIosData->fEndOfStream = false; 1398 pIosData->hVfsIos = pThis->hVfsIos; 1077 1399 RTVfsIoStrmRetain(pThis->hVfsIos); 1078 1400 … … 1091 1413 * fitting VFS type alternative. 1092 1414 */ 1093 case RTZIPTAR_TF_LINK: 1094 case RTZIPTAR_TF_SYMLINK: 1415 case RTFS_TYPE_SYMLINK: 1095 1416 { 1096 1417 RTVFSSYMLINK hVfsSym; … … 1105 1426 return pThis->rcFatal = rc; 1106 1427 1107 pBaseObjData->offHdr = off;1108 pBaseObjData-> Hdr = Hdr;1109 pBaseObjData->ObjInfo = Info;1428 pBaseObjData->offHdr = offHdr; 1429 pBaseObjData->pTarReader= &pThis->TarReader; 1430 pBaseObjData->ObjInfo = Info; 1110 1431 1111 1432 enmType = RTVFSOBJTYPE_SYMLINK; … … 1117 1438 /* 1118 1439 * All other objects are repesented using a VFS base object since they 1119 * carry no data streams (unless some tarextension implements extended1440 * carry no data streams (unless some TAR extension implements extended 1120 1441 * attributes / alternative streams). 1121 1442 */ 1122 case RT ZIPTAR_TF_CHR:1123 case RT ZIPTAR_TF_BLK:1124 case RT ZIPTAR_TF_DIR:1125 case RT ZIPTAR_TF_FIFO:1443 case RTFS_TYPE_DEV_BLOCK: 1444 case RTFS_TYPE_DEV_CHAR: 1445 case RTFS_TYPE_DIRECTORY: 1446 case RTFS_TYPE_FIFO: 1126 1447 { 1127 1448 PRTZIPTARBASEOBJ pBaseObjData; … … 1135 1456 return pThis->rcFatal = rc; 1136 1457 1137 pBaseObjData->offHdr = off;1138 pBaseObjData-> Hdr = Hdr;1139 pBaseObjData->ObjInfo = Info;1458 pBaseObjData->offHdr = offHdr; 1459 pBaseObjData->pTarReader= &pThis->TarReader; 1460 pBaseObjData->ObjInfo = Info; 1140 1461 1141 1462 enmType = RTVFSOBJTYPE_BASE; … … 1154 1475 if (ppszName) 1155 1476 { 1156 if (rtZipTarHdrHasPrefix(&Hdr)) 1157 { 1158 *ppszName = NULL; 1159 rc = RTStrAAppendExN(ppszName, 3, 1160 Hdr.Posix.prefix, sizeof(Hdr.Posix.prefix), 1161 "/", 1, 1162 Hdr.Posix.name, sizeof(Hdr.Posix.name)); 1163 } 1164 else 1165 { 1166 *ppszName = RTStrDupN(Hdr.Posix.name, sizeof(Hdr.Posix.name)); 1167 rc = *ppszName ? VINF_SUCCESS : VERR_NO_STR_MEMORY; 1168 } 1477 rc = RTStrDupEx(ppszName, pThis->TarReader.szName); 1169 1478 if (RT_FAILURE(rc)) 1170 1479 return rc; … … 1229 1538 if (RT_SUCCESS(rc)) 1230 1539 { 1231 pThis->hVfsIos = hVfsIosIn; 1232 pThis->hVfsCurObj = NIL_RTVFSOBJ; 1233 pThis->pCurIosData = NULL; 1234 pThis->offStart = offStart; 1235 pThis->offNextHdr = offStart; 1236 pThis->fEndOfStream = false; 1237 pThis->rcFatal = VINF_SUCCESS; 1540 pThis->hVfsIos = hVfsIosIn; 1541 pThis->hVfsCurObj = NIL_RTVFSOBJ; 1542 pThis->pCurIosData = NULL; 1543 pThis->offStart = offStart; 1544 pThis->offNextHdr = offStart; 1545 pThis->fEndOfStream = false; 1546 pThis->rcFatal = VINF_SUCCESS; 1547 pThis->TarReader.enmPrevType= RTZIPTARTYPE_INVALID; 1548 pThis->TarReader.enmType = RTZIPTARTYPE_INVALID; 1549 pThis->TarReader.enmState = RTZIPTARREADERSTATE_FIRST; 1238 1550 1239 1551 /* Don't check if it's a TAR stream here, do that in the
Note:
See TracChangeset
for help on using the changeset viewer.