Changeset 48838 in vbox
- Timestamp:
- Oct 3, 2013 1:42:45 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/err.h
r48797 r48838 1840 1840 /** Bad size element in table of content sub-element. */ 1841 1841 #define VERR_XAR_BAD_SIZE_ELEMENT (-22721) 1842 /** Missing length element in table of content sub-element. */ 1843 #define VERR_XAR_MISSING_LENGTH_ELEMENT (-22722) 1844 /** Bad length element in table of content sub-element. */ 1845 #define VERR_XAR_BAD_LENGTH_ELEMENT (-22723) 1842 1846 /** Bad file element in XAR table of content. */ 1843 #define VERR_XAR_BAD_FILE_ELEMENT (-2272 2)1844 /** An data element is expected for XAR file of typefile. */1845 #define VERR_XAR_ DATA_NODE_NOT_FOUND (-22723)1847 #define VERR_XAR_BAD_FILE_ELEMENT (-22724) 1848 /** Missing data element for XAR file. */ 1849 #define VERR_XAR_MISSING_DATA_ELEMENT (-22725) 1846 1850 /** Unknown XAR file type value. */ 1847 #define VERR_XAR_BAD_UNKNOWN_FILE_TYPE (-22724) 1851 #define VERR_XAR_UNKNOWN_FILE_TYPE (-22726) 1852 /** Missing encoding element for XAR data stream. */ 1853 #define VERR_XAR_NO_ENCODING (-22727) 1854 /** Bad timestamp for XAR file. */ 1855 #define VERR_XAR_BAD_FILE_TIMESTAMP (-22728) 1856 /** Bad file mode for XAR file. */ 1857 #define VERR_XAR_BAD_FILE_MODE (-22729) 1858 /** Bad file user id for XAR file. */ 1859 #define VERR_XAR_BAD_FILE_UID (-22730) 1860 /** Bad file group id for XAR file. */ 1861 #define VERR_XAR_BAD_FILE_GID (-22731) 1862 /** Bad file inode device number for XAR file. */ 1863 #define VERR_XAR_BAD_FILE_DEVICE_NO (-22732) 1864 /** Bad file inode number for XAR file. */ 1865 #define VERR_XAR_BAD_FILE_INODE (-22733) 1866 /** Invalid name for XAR file. */ 1867 #define VERR_XAR_INVALID_FILE_NAME (-22734) 1868 /** The message digest of the extracted data does not match the one supplied. */ 1869 #define VERR_XAR_EXTRACTED_HASH_MISMATCH (-22735) 1870 /** The extracted data has exceeded the expected size. */ 1871 #define VERR_XAR_EXTRACTED_SIZE_EXCEEDED (-22736) 1872 /** The message digest of the archived data does not match the one supplied. */ 1873 #define VERR_XAR_ARCHIVED_HASH_MISMATCH (-22737) 1874 /** The decompressor completed without using all the input data. */ 1875 #define VERR_XAR_UNUSED_ARCHIVED_DATA (-22738) 1876 /** Expected the archived and extracted XAR data sizes to be the same for 1877 * uncompressed data. */ 1878 #define VERR_XAR_ARCHIVED_AND_EXTRACTED_SIZES_MISMATCH (-22739) 1848 1879 /** @} */ 1849 1880 -
trunk/src/VBox/Runtime/common/zip/xarvfs.cpp
r48797 r48838 47 47 48 48 49 /******************************************************************************* 50 * Defined Constants And Macros * 51 *******************************************************************************/ 52 /** @name Hash state 53 * @{ */ 54 #define RTZIPXAR_HASH_PENDING 0 55 #define RTZIPXAR_HASH_OK 1 56 #define RTZIPXAR_HASH_FAILED_ARCHIVED 2 57 #define RTZIPXAR_HASH_FAILED_EXTRACTED 3 58 /** @} */ 59 49 60 50 61 /******************************************************************************* … … 53 64 /** 54 65 * Hash digest value union for the supported XAR hash functions. 66 * @todo This could be generalized in iprt/checksum.h or somewhere. 55 67 */ 56 68 typedef union RTZIPXARHASHDIGEST … … 65 77 66 78 /** 79 * Hash context union. 80 */ 81 typedef union RTZIPXARHASHCTX 82 { 83 RTMD5CONTEXT Md5; 84 RTSHA1CONTEXT Sha1; 85 } RTZIPXARHASHCTX; 86 /** Pointer to a hash context union. */ 87 typedef RTZIPXARHASHCTX *PRTZIPXARHASHCTX; 88 89 /** 67 90 * XAR reader instance data. 68 91 */ … … 78 101 /** The depth of the current file, with 0 being the root level. */ 79 102 uint32_t cCurDepth; 80 /** Set if it's the first file. */81 bool fFirstFile;82 103 } RTZIPXARREADER; 83 104 /** Pointer to the XAR reader instance data. */ … … 89 110 typedef struct RTZIPXARBASEOBJ 90 111 { 91 /** Pointer to the reader instance data (resides in the filesystem92 * stream).93 * @todo Fix this so it won't go stale... Back ref from this obj to fss? */94 PRTZIPXARREADER pXarReader;95 112 /** The file TOC element. */ 96 113 xml::ElementNode const *pFileElem; 114 /** RTFS_TYPE_XXX value for the object. */ 115 RTFMODE fModeType; 97 116 } RTZIPXARBASEOBJ; 98 117 /** Pointer to a XAR filesystem stream base object. */ … … 118 137 typedef struct RTZIPXARDATASTREAM 119 138 { 120 /** Offset of the data in the stream, relative to XARREADER::offZero. */ 139 /** Offset of the data in the stream. 140 * @remarks The I/O stream and file constructor will adjust this so that it 141 * relative to the start of the input stream, instead of the first byte 142 * after the TOC. */ 121 143 RTFOFF offData; 122 144 /** The size of the archived data. */ 123 RTFOFFcbDataArchived;145 uint64_t cbDataArchived; 124 146 /** The size of the extracted data. */ 125 RTFOFFcbDataExtracted;147 uint64_t cbDataExtracted; 126 148 /** The encoding of the archived ata. */ 127 149 RTZIPXARENCODING enmEncoding; … … 147 169 RTZIPXARBASEOBJ BaseObj; 148 170 /** The attributes of the primary data stream. */ 149 RTZIPXARDATASTREAM Data ;150 /** The current file position . */151 RTFOFF off File;171 RTZIPXARDATASTREAM DataAttr; 172 /** The current file position in the archived file. */ 173 RTFOFF offCurPos; 152 174 /** The input I/O stream. */ 153 175 RTVFSIOSTREAM hVfsIos; 154 /** Set if we've reached the end of the file. */ 176 /** Set if we've reached the end of the file or if the next object in the 177 * file system stream has been requested. */ 155 178 bool fEndOfStream; 179 /** Whether the stream is seekable. */ 180 bool fSeekable; 181 /** Hash state. */ 182 uint8_t uHashState; 156 183 /** The size of the file that we've currently hashed. 157 184 * We use this to check whether the user skips part of the file while reading … … 159 186 RTFOFF cbDigested; 160 187 /** The digest of the archived data. */ 161 RTZIPXARHASH DIGEST DigestArchived;188 RTZIPXARHASHCTX CtxArchived; 162 189 /** The digest of the extracted data. */ 163 RTZIPXARHASH DIGEST DigestExtracted;190 RTZIPXARHASHCTX CtxExtracted; 164 191 } RTZIPXARIOSTREAM; 165 192 /** Pointer to a the private data of a XAR file I/O stream. */ … … 172 199 typedef struct RTZIPXARFILE 173 200 { 174 /** The XAR I/O stream object. */175 RTZIPXARIOSTREAM Ios Obj;201 /** The XAR I/O stream data. */ 202 RTZIPXARIOSTREAM Ios; 176 203 /** The input file. */ 177 204 RTVFSFILE hVfsFile; 178 205 } RTZIPXARFILE; 179 /** Pointer to athe private data of a XAR file. */206 /** Pointer to the private data of a XAR file. */ 180 207 typedef RTZIPXARFILE *PRTZIPXARFILE; 208 209 210 /** 211 * Decompressed I/O stream instance. 212 * 213 * This is just a front that checks digests and other sanity stuff. 214 */ 215 typedef struct RTZIPXARDECOMPIOS 216 { 217 /** The decompressor I/O stream. */ 218 RTVFSIOSTREAM hVfsIosDecompressor; 219 /** The raw XAR I/O stream. */ 220 RTVFSIOSTREAM hVfsIosRaw; 221 /** Pointer to the raw XAR I/O stream instance data. */ 222 PRTZIPXARIOSTREAM pIosRaw; 223 /** The current file position in the archived file. */ 224 RTFOFF offCurPos; 225 /** The hash function to use on the extracted data. */ 226 uint8_t uHashFunExtracted; 227 /** Hash state on the extracted data. */ 228 uint8_t uHashState; 229 /** The digest of the extracted data. */ 230 RTZIPXARHASHCTX CtxExtracted; 231 /** The expected digest of the extracted data. */ 232 RTZIPXARHASHDIGEST DigestExtracted; 233 } RTZIPXARDECOMPIOS; 234 /** Pointer to the private data of a XAR decompressed I/O stream. */ 235 typedef RTZIPXARDECOMPIOS *PRTZIPXARDECOMPIOS; 181 236 182 237 … … 190 245 /** The input file, if the stream is actually a file. */ 191 246 RTVFSFILE hVfsFile; 192 193 /** The current object (referenced). */194 RTVFSOBJ hVfsCurObj;195 /** Pointer to the private data if hVfsCurObj is representing a file. */196 PRTZIPXARIOSTREAM pCurIosData;197 247 198 248 /** The start offset in the input I/O stream. */ … … 225 275 * @param pvSrc The data to hash. 226 276 * @param cbSrc The size of the data to hash. 227 * @param pHashDigest Where to return the hashdigest.277 * @param pHashDigest Where to return the message digest. 228 278 */ 229 279 static void rtZipXarCalcHash(uint32_t uHashFunction, void const *pvSrc, size_t cbSrc, PRTZIPXARHASHDIGEST pHashDigest) … … 244 294 245 295 246 static int rtZipXarGetOffsetSizeFromElem(xml::ElementNode const *pElement, PRTFOFF poff, uint64_t *pcb) 247 { 248 if (pElement) 249 return VERR_XAR_DATA_NODE_NOT_FOUND; 250 296 /** 297 * Initializes a hash context. 298 * 299 * @param pCtx Pointer to the context union. 300 * @param uHashFunction The hash function to use. 301 */ 302 static void rtZipXarHashInit(PRTZIPXARHASHCTX pCtx, uint32_t uHashFunction) 303 { 304 switch (uHashFunction) 305 { 306 case XAR_HASH_SHA1: 307 RTSha1Init(&pCtx->Sha1); 308 break; 309 case XAR_HASH_MD5: 310 RTMd5Init(&pCtx->Md5);; 311 break; 312 default: 313 RT_ZERO(*pCtx); 314 break; 315 } 316 } 317 318 319 /** 320 * Adds a block to the hash calculation. 321 * 322 * @param pCtx Pointer to the context union. 323 * @param uHashFunction The hash function to use. 324 * @param pvSrc The data to add to the hash. 325 * @param cbSrc The size of the data. 326 */ 327 static void rtZipXarHashUpdate(PRTZIPXARHASHCTX pCtx, uint32_t uHashFunction, void const *pvSrc, size_t cbSrc) 328 { 329 switch (uHashFunction) 330 { 331 case XAR_HASH_SHA1: 332 RTSha1Update(&pCtx->Sha1, pvSrc, cbSrc); 333 break; 334 case XAR_HASH_MD5: 335 RTMd5Update(&pCtx->Md5, pvSrc, cbSrc); 336 break; 337 } 338 } 339 340 341 /** 342 * Finalizes the hash, producing the message digest. 343 * 344 * @param pCtx Pointer to the context union. 345 * @param uHashFunction The hash function to use. 346 * @param pHashDigest Where to return the message digest. 347 */ 348 static void rtZipXarHashFinal(PRTZIPXARHASHCTX pCtx, uint32_t uHashFunction, PRTZIPXARHASHDIGEST pHashDigest) 349 { 350 switch (uHashFunction) 351 { 352 case XAR_HASH_SHA1: 353 RTSha1Final(&pCtx->Sha1, pHashDigest->abSha1); 354 break; 355 case XAR_HASH_MD5: 356 RTMd5Final(pHashDigest->abMd5, &pCtx->Md5); 357 break; 358 default: 359 RT_ZERO(*pHashDigest); 360 break; 361 } 362 } 363 364 365 /** 366 * Compares two hash digests. 367 * 368 * @returns true if equal, false if not. 369 * @param uHashFunction The hash function to use. 370 * @param pHashDigest1 The first hash digest. 371 * @param pHashDigest2 The second hash digest. 372 */ 373 static bool rtZipXarHashIsEqual(uint32_t uHashFunction, PRTZIPXARHASHDIGEST pHashDigest1, PRTZIPXARHASHDIGEST pHashDigest2) 374 { 375 switch (uHashFunction) 376 { 377 case XAR_HASH_SHA1: 378 return memcmp(pHashDigest1->abSha1, pHashDigest2->abSha1, sizeof(pHashDigest1->abSha1)) == 0; 379 case XAR_HASH_MD5: 380 return memcmp(pHashDigest1->abMd5, pHashDigest2->abMd5, sizeof(pHashDigest1->abMd5)) == 0; 381 default: 382 return true; 383 } 384 } 385 386 387 /** 388 * Gets the 'offset', 'size' and optionally 'length' sub elements. 389 * 390 * @returns IPRT status code. 391 * @param pElement The parent element. 392 * @param poff Where to return the offset value. 393 * @param pcbSize Where to return the size value. 394 * @param pcbLength Where to return the length value, optional. 395 */ 396 static int rtZipXarGetOffsetSizeLengthFromElem(xml::ElementNode const *pElement, 397 PRTFOFF poff, uint64_t *pcbSize, uint64_t *pcbLength) 398 { 251 399 /* 252 400 * The offset. … … 267 415 268 416 /* 269 * The size.417 * The 'size' stored in the archive. 270 418 */ 271 419 pElem = pElement->findChildElement("size"); … … 277 425 return VERR_XAR_BAD_SIZE_ELEMENT; 278 426 279 rc = RTStrToUInt64Full(pszValue, 0, pcb );427 rc = RTStrToUInt64Full(pszValue, 0, pcbSize); 280 428 if ( RT_FAILURE(rc) 281 429 || rc == VWRN_NUMBER_TOO_BIG 282 || *pcb > UINT64_MAX / 2 /* prevent overflow should be use it for calcuations later. */)430 || *pcbSize >= UINT64_MAX / 2 /* prevent overflow casting to RTFOFF_MAX. */) 283 431 return VERR_XAR_BAD_SIZE_ELEMENT; 432 AssertCompile(RTFOFF_MAX == UINT64_MAX / 2); 433 434 /* 435 * The 'length' of the uncompressed data. Not present for checksums, so 436 * the caller might not want it. 437 */ 438 if (pcbLength) 439 { 440 pElem = pElement->findChildElement("length"); 441 if (!pElem) 442 return VERR_XAR_MISSING_LENGTH_ELEMENT; 443 444 pszValue = pElem->getValue(); 445 if (!pszValue) 446 return VERR_XAR_BAD_LENGTH_ELEMENT; 447 448 rc = RTStrToUInt64Full(pszValue, 0, pcbLength); 449 if ( RT_FAILURE(rc) 450 || rc == VWRN_NUMBER_TOO_BIG 451 || *pcbLength >= UINT64_MAX / 2 /* prevent overflow casting to RTFOFF_MAX. */) 452 return VERR_XAR_BAD_LENGTH_ELEMENT; 453 AssertCompile(RTFOFF_MAX == UINT64_MAX / 2); 454 } 284 455 285 456 return VINF_SUCCESS; … … 288 459 289 460 /** 290 * Translate a XAR header to an IPRT object info structure with additional UNIX 291 * attributes. 292 * 293 * This completes the validation done by rtZipXarHdrValidate. 294 * 295 * @returns VINF_SUCCESS if valid, appropriate VERR_XAR_XXX if not. 296 * @param pThis The XAR reader instance. 297 * @param pObjInfo The object info structure (output). 298 */ 299 static int rtZipXarReaderGetFsObjInfo(PRTZIPXARREADER pThis, PRTFSOBJINFO pObjInfo) 300 { 301 /* 302 * Zap the whole structure, this takes care of unused space in the union. 303 */ 304 RT_ZERO(*pObjInfo); 305 306 #if 0 307 /* 308 * Convert the XAR field in RTFSOBJINFO order. 309 */ 310 int rc; 311 int64_t i64Tmp; 312 #define GET_XAR_NUMERIC_FIELD_RET(a_Var, a_Field) \ 313 do { \ 314 rc = rtZipXarHdrFieldToNum(a_Field, sizeof(a_Field), false /*fOctalOnly*/, &i64Tmp); \ 315 if (RT_FAILURE(rc)) \ 316 return rc; \ 317 (a_Var) = i64Tmp; \ 318 if ((a_Var) != i64Tmp) \ 319 return VERR_XAR_NUM_VALUE_TOO_LARGE; \ 320 } while (0) 321 322 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->cbObject, pThis->Hdr.Common.size); 323 pObjInfo->cbAllocated = RT_ALIGN_64(pObjInfo->cbObject, 512); 324 int64_t c64SecModTime; 325 GET_XAR_NUMERIC_FIELD_RET(c64SecModTime, pThis->Hdr.Common.mtime); 326 RTTimeSpecSetSeconds(&pObjInfo->ChangeTime, c64SecModTime); 327 RTTimeSpecSetSeconds(&pObjInfo->ModificationTime, c64SecModTime); 328 RTTimeSpecSetSeconds(&pObjInfo->AccessTime, c64SecModTime); 329 RTTimeSpecSetSeconds(&pObjInfo->BirthTime, c64SecModTime); 330 if (c64SecModTime != RTTimeSpecGetSeconds(&pObjInfo->ModificationTime)) 331 return VERR_XAR_NUM_VALUE_TOO_LARGE; 332 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->Attr.fMode, pThis->Hdr.Common.mode); 333 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX; 334 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.uid, pThis->Hdr.Common.uid); 335 GET_XAR_NUMERIC_FIELD_RET(pObjInfo->Attr.u.Unix.gid, pThis->Hdr.Common.gid); 336 pObjInfo->Attr.u.Unix.cHardlinks = 1; 337 pObjInfo->Attr.u.Unix.INodeIdDevice = 0; 338 pObjInfo->Attr.u.Unix.INodeId = 0; 339 pObjInfo->Attr.u.Unix.fFlags = 0; 340 pObjInfo->Attr.u.Unix.GenerationId = 0; 341 pObjInfo->Attr.u.Unix.Device = 0; 342 switch (pThis->enmType) 343 { 344 case RTZIPXARTYPE_POSIX: 345 case RTZIPXARTYPE_GNU: 346 if ( pThis->Hdr.Common.typeflag == RTZIPXAR_TF_CHR 347 || pThis->Hdr.Common.typeflag == RTZIPXAR_TF_BLK) 348 { 349 uint32_t uMajor, uMinor; 350 GET_XAR_NUMERIC_FIELD_RET(uMajor, pThis->Hdr.Common.devmajor); 351 GET_XAR_NUMERIC_FIELD_RET(uMinor, pThis->Hdr.Common.devminor); 352 pObjInfo->Attr.u.Unix.Device = RTDEV_MAKE(uMajor, uMinor); 353 if ( uMajor != RTDEV_MAJOR(pObjInfo->Attr.u.Unix.Device) 354 || uMinor != RTDEV_MINOR(pObjInfo->Attr.u.Unix.Device)) 355 return VERR_XAR_DEV_VALUE_TOO_LARGE; 356 } 461 * Convers a checksum style value into a XAR hash function number. 462 * 463 * @returns IPRT status code. 464 * @param pszStyle The XAR checksum style. 465 * @param puHashFunction Where to return the hash function number on success. 466 */ 467 static int rtZipXarParseChecksumStyle(const char *pszStyle, uint8_t *puHashFunction) 468 { 469 if (!strcmp(pszStyle, "sha1")) 470 *puHashFunction = XAR_HASH_SHA1; 471 else if (!strcmp(pszStyle, "md5")) 472 *puHashFunction = XAR_HASH_MD5; 473 else if (!strcmp(pszStyle, "none")) 474 *puHashFunction = XAR_HASH_NONE; 475 else 476 { 477 *puHashFunction = UINT8_MAX; 478 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 479 } 480 return VINF_SUCCESS; 481 } 482 483 484 /** 485 * Parses a checksum element typically found under 'data'. 486 * 487 * @returns IPRT status code. 488 * @param pParentElem The parent element ('data'). 489 * @param pszName The name of the element, like 'checksum-archived' or 490 * 'checksum-extracted'. 491 * @param puHashFunction Where to return the XAR hash function number. 492 * @param pDigest Where to return the expected message digest. 493 */ 494 static int rtZipXarParseChecksumElem(xml::ElementNode const *pParentElem, const char *pszName, 495 uint8_t *puHashFunction, PRTZIPXARHASHDIGEST pDigest) 496 { 497 /* Default is no checksum. */ 498 *puHashFunction = XAR_HASH_NONE; 499 RT_ZERO(*pDigest); 500 501 xml::ElementNode const *pChecksumElem = pParentElem->findChildElement(pszName); 502 if (!pChecksumElem) 503 return VINF_SUCCESS; 504 505 /* The style. */ 506 const char *pszStyle = pChecksumElem->findAttributeValue("style"); 507 if (!pszStyle) 508 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 509 int rc = rtZipXarParseChecksumStyle(pszStyle, puHashFunction); 510 if (RT_FAILURE(rc)) 511 return rc; 512 513 if (*puHashFunction == XAR_HASH_NONE) 514 return VINF_SUCCESS; 515 516 /* The digest. */ 517 const char *pszDigest = pChecksumElem->getValue(); 518 if (!pszDigest) 519 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 520 521 switch (*puHashFunction) 522 { 523 case XAR_HASH_SHA1: 524 rc = RTSha1FromString(pszDigest, pDigest->abSha1); 357 525 break; 358 526 case XAR_HASH_MD5: 527 rc = RTMd5FromString(pszDigest, pDigest->abMd5); 528 break; 359 529 default: 360 if ( pThis->Hdr.Common.typeflag == RTZIPXAR_TF_CHR 361 || pThis->Hdr.Common.typeflag == RTZIPXAR_TF_BLK) 362 return VERR_XAR_UNKNOWN_TYPE_FLAG; 363 } 364 365 #undef GET_XAR_NUMERIC_FIELD_RET 366 367 /* 368 * Massage the result a little bit. 369 * Also validate some more now that we've got the numbers to work with. 370 */ 371 if ( (pObjInfo->Attr.fMode & ~RTFS_UNIX_MASK) 372 && pThis->enmType == RTZIPXARTYPE_POSIX) 373 return VERR_XAR_BAD_MODE_FIELD; 374 pObjInfo->Attr.fMode &= RTFS_UNIX_MASK; 375 376 RTFMODE fModeType = 0; 377 switch (pThis->Hdr.Common.typeflag) 378 { 379 case RTZIPXAR_TF_OLDNORMAL: 380 case RTZIPXAR_TF_NORMAL: 381 case RTZIPXAR_TF_CONTIG: 382 { 383 const char *pszEnd = strchr(pThis->szName, '\0'); 384 if (pszEnd == &pThis->szName[0] || pszEnd[-1] != '/') 385 fModeType |= RTFS_TYPE_FILE; 386 else 387 fModeType |= RTFS_TYPE_DIRECTORY; 530 rc = VERR_INTERNAL_ERROR_2; 531 } 532 return rc; 533 } 534 535 536 /** 537 * Gets all the attributes of the primary data stream. 538 * 539 * @returns IPRT status code. 540 * @param pFileElem The file element, we'll be parsing the 'data' 541 * sub element of this. 542 * @param pDataAttr Where to return the attributes. 543 */ 544 static int rtZipXarGetDataStreamAttributes(xml::ElementNode const *pFileElem, PRTZIPXARDATASTREAM pDataAttr) 545 { 546 /* 547 * Get the data element. 548 */ 549 xml::ElementNode const *pDataElem = pFileElem->findChildElement("data"); 550 if (!pDataElem) 551 return VERR_XAR_MISSING_DATA_ELEMENT; 552 553 /* 554 * Checksums. 555 */ 556 int rc = rtZipXarParseChecksumElem(pDataElem, "extracted-checksum", 557 &pDataAttr->uHashFunExtracted, &pDataAttr->DigestExtracted); 558 if (RT_FAILURE(rc)) 559 return rc; 560 rc = rtZipXarParseChecksumElem(pDataElem, "archived-checksum", 561 &pDataAttr->uHashFunArchived, &pDataAttr->DigestArchived); 562 if (RT_FAILURE(rc)) 563 return rc; 564 565 /* 566 * The encoding. 567 */ 568 const char *pszEncoding = pDataElem->findChildElementAttributeValueP("encoding", "style"); 569 if (!pszEncoding) 570 return VERR_XAR_NO_ENCODING; 571 if (!strcmp(pszEncoding, "application/octet-stream")) 572 pDataAttr->enmEncoding = RTZIPXARENCODING_STORE; 573 else if (!strcmp(pszEncoding, "application/x-gzip")) 574 pDataAttr->enmEncoding = RTZIPXARENCODING_GZIP; 575 else 576 pDataAttr->enmEncoding = RTZIPXARENCODING_UNSUPPORTED; 577 578 /* 579 * The data offset and the compressed and uncompressed sizes. 580 */ 581 rc = rtZipXarGetOffsetSizeLengthFromElem(pDataElem, &pDataAttr->offData, 582 &pDataAttr->cbDataExtracted, &pDataAttr->cbDataArchived); 583 if (RT_FAILURE(rc)) 584 return rc; 585 586 /* No zero padding or other alignment crap, please. */ 587 if ( pDataAttr->enmEncoding == RTZIPXARENCODING_STORE 588 && pDataAttr->cbDataExtracted != pDataAttr->cbDataArchived) 589 return VERR_XAR_ARCHIVED_AND_EXTRACTED_SIZES_MISMATCH; 590 591 return VINF_SUCCESS; 592 } 593 594 595 /** 596 * Parses a timestamp. 597 * 598 * We consider all timestamps optional, and will only fail (return @c false) on 599 * parse errors. If the specified element isn't found, we'll return epoc time. 600 * 601 * @returns boolean success indicator. 602 * @param pParent The parent element (typically 'file'). 603 * @param pszChild The name of the child element. 604 * @param pTimeSpec Where to return the timespec on success. 605 */ 606 static bool rtZipXarParseTimestamp(const xml::ElementNode *pParent, const char *pszChild, PRTTIMESPEC pTimeSpec) 607 { 608 const char *pszValue = pParent->findChildElementValueP(pszChild); 609 if (pszValue) 610 { 611 if (RTTimeSpecFromString(pTimeSpec, pszValue)) 612 return true; 613 return false; 614 } 615 RTTimeSpecSetNano(pTimeSpec, 0); 616 return true; 617 } 618 619 620 /** 621 * Gets the next file element in the TOC. 622 * 623 * @returns Pointer to the next file, NULL if we've reached the end. 624 * @param pCurFile The current element. 625 * @param pcCurDepth Depth gauge we update when decending and 626 * acending thru the tree. 627 */ 628 static xml::ElementNode const *rtZipXarGetNextFileElement(xml::ElementNode const *pCurFile, uint32_t *pcCurDepth) 629 { 630 /* 631 * Consider children first. 632 */ 633 xml::ElementNode const *pChild = pCurFile->findChildElement("file"); 634 if (pChild) 635 { 636 *pcCurDepth += 1; 637 return pChild; 638 } 639 640 /* 641 * Siblings and ancestor siblings. 642 */ 643 for (;;) 644 { 645 xml::ElementNode const *pSibling = pCurFile->findNextSibilingElement("file"); 646 if (pSibling != NULL) 647 return pSibling; 648 649 if (*pcCurDepth == 0) 388 650 break; 389 } 390 391 case RTZIPXAR_TF_LINK: 392 if (pObjInfo->cbObject != 0) 393 #if 0 /* too strict */ 394 return VERR_XAR_SIZE_NOT_ZERO; 395 #else 396 pObjInfo->cbObject = pObjInfo->cbAllocated = 0; 397 #endif 398 fModeType |= RTFS_TYPE_FILE; /* no better idea for now */ 399 break; 400 401 case RTZIPXAR_TF_SYMLINK: 402 fModeType |= RTFS_TYPE_SYMLINK; 403 break; 404 405 case RTZIPXAR_TF_CHR: 406 fModeType |= RTFS_TYPE_DEV_CHAR; 407 break; 408 409 case RTZIPXAR_TF_BLK: 410 fModeType |= RTFS_TYPE_DEV_BLOCK; 411 break; 412 413 case RTZIPXAR_TF_DIR: 414 fModeType |= RTFS_TYPE_DIRECTORY; 415 break; 416 417 case RTZIPXAR_TF_FIFO: 418 fModeType |= RTFS_TYPE_FIFO; 419 break; 420 421 case RTZIPXAR_TF_GNU_LONGLINK: 422 case RTZIPXAR_TF_GNU_LONGNAME: 423 /* ASSUMES RTFS_TYPE_XXX uses the same values as GNU stored in the mode field. */ 424 fModeType = pObjInfo->Attr.fMode & RTFS_TYPE_MASK; 425 switch (fModeType) 426 { 427 case RTFS_TYPE_FILE: 428 case RTFS_TYPE_DIRECTORY: 429 case RTFS_TYPE_SYMLINK: 430 case RTFS_TYPE_DEV_BLOCK: 431 case RTFS_TYPE_DEV_CHAR: 432 case RTFS_TYPE_FIFO: 433 break; 434 435 default: 436 case 0: 437 return VERR_XAR_UNKNOWN_TYPE_FLAG; /** @todo new status code */ 438 } 439 440 default: 441 return VERR_XAR_UNKNOWN_TYPE_FLAG; /* Should've been caught in validate. */ 442 } 443 if ( (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) 444 && (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) != fModeType) 445 return VERR_XAR_MODE_WITH_TYPE; 446 pObjInfo->Attr.fMode &= ~RTFS_TYPE_MASK; 447 pObjInfo->Attr.fMode |= fModeType; 448 449 switch (pThis->Hdr.Common.typeflag) 450 { 451 case RTZIPXAR_TF_CHR: 452 case RTZIPXAR_TF_BLK: 453 case RTZIPXAR_TF_DIR: 454 case RTZIPXAR_TF_FIFO: 455 pObjInfo->cbObject = 0; 456 pObjInfo->cbAllocated = 0; 457 break; 458 } 459 #endif 460 461 return VINF_SUCCESS; 651 *pcCurDepth -= 1; 652 pCurFile = static_cast<const xml::ElementNode *>(pCurFile->getParent()); 653 AssertBreak(pCurFile); 654 Assert(pCurFile->nameEquals("file")); 655 } 656 657 return NULL; 462 658 } 463 659 … … 472 668 */ 473 669 670 474 671 /** 475 672 * @interface_method_impl{RTVFSOBJOPS,pfnClose} … … 493 690 PRTZIPXARBASEOBJ pThis = (PRTZIPXARBASEOBJ)pvThis; 494 691 495 #if 0 692 /* 693 * Get the common data. 694 */ 695 696 /* Sizes. */ 697 if (pThis->fModeType == RTFS_TYPE_FILE) 698 { 699 PRTZIPXARIOSTREAM pThisIos = RT_FROM_MEMBER(pThis, RTZIPXARIOSTREAM, BaseObj); 700 pObjInfo->cbObject = pThisIos->DataAttr.cbDataArchived; /* Modified by decomp ios. */ 701 pObjInfo->cbAllocated = pThisIos->DataAttr.cbDataArchived; 702 } 703 else 704 { 705 pObjInfo->cbObject = 0; 706 pObjInfo->cbAllocated = 0; 707 } 708 709 /* The file mode. */ 710 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("mode", 0755, &pObjInfo->Attr.fMode))) 711 return VERR_XAR_BAD_FILE_MODE; 712 if (pObjInfo->Attr.fMode & RTFS_TYPE_MASK) 713 return VERR_XAR_BAD_FILE_MODE; 714 pObjInfo->Attr.fMode &= RTFS_UNIX_MASK & ~RTFS_TYPE_MASK; 715 pObjInfo->Attr.fMode |= pThis->fModeType; 716 717 /* File times. */ 718 if (RT_UNLIKELY(!rtZipXarParseTimestamp(pThis->pFileElem, "atime", &pObjInfo->AccessTime))) 719 return VERR_XAR_BAD_FILE_TIMESTAMP; 720 if (RT_UNLIKELY(!rtZipXarParseTimestamp(pThis->pFileElem, "ctime", &pObjInfo->ChangeTime))) 721 return VERR_XAR_BAD_FILE_TIMESTAMP; 722 if (RT_UNLIKELY(!rtZipXarParseTimestamp(pThis->pFileElem, "mtime", &pObjInfo->ModificationTime))) 723 return VERR_XAR_BAD_FILE_TIMESTAMP; 724 pObjInfo->BirthTime = RTTimeSpecGetNano(&pObjInfo->AccessTime) <= RTTimeSpecGetNano(&pObjInfo->ChangeTime) 725 ? pObjInfo->AccessTime : pObjInfo->ChangeTime; 726 if (RTTimeSpecGetNano(&pObjInfo->BirthTime) > RTTimeSpecGetNano(&pObjInfo->ModificationTime)) 727 pObjInfo->BirthTime = pObjInfo->ModificationTime; 728 496 729 /* 497 730 * Copy the desired data. … … 501 734 case RTFSOBJATTRADD_NOTHING: 502 735 case RTFSOBJATTRADD_UNIX: 503 *pObjInfo = pThis->ObjInfo; 736 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX; 737 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("uid", 0, &pObjInfo->Attr.u.Unix.uid))) 738 return VERR_XAR_BAD_FILE_UID; 739 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("gid", 0, &pObjInfo->Attr.u.Unix.gid))) 740 return VERR_XAR_BAD_FILE_GID; 741 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("deviceno", 0, &pObjInfo->Attr.u.Unix.INodeIdDevice))) 742 return VERR_XAR_BAD_FILE_DEVICE_NO; 743 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("inode", 0, &pObjInfo->Attr.u.Unix.INodeId))) 744 return VERR_XAR_BAD_FILE_INODE; 745 pObjInfo->Attr.u.Unix.cHardlinks = 1; 746 pObjInfo->Attr.u.Unix.fFlags = 0; 747 pObjInfo->Attr.u.Unix.GenerationId = 0; 748 pObjInfo->Attr.u.Unix.Device = 0; 504 749 break; 505 750 506 751 case RTFSOBJATTRADD_UNIX_OWNER: 507 *pObjInfo = pThis->ObjInfo; 508 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER; 509 pObjInfo->Attr.u.UnixOwner.uid = pThis->ObjInfo.Attr.u.Unix.uid; 510 pObjInfo->Attr.u.UnixOwner.szName[0] = '\0'; 511 if (rtZipXarReaderHasUserName(pThis->pXarReader)) 512 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), 513 pThis->pXarReader->Hdr.Common.uname); 752 { 753 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER; 754 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("uid", 0, &pObjInfo->Attr.u.Unix.uid))) 755 return VERR_XAR_BAD_FILE_UID; 756 const char *pszUser = pThis->pFileElem->findChildElementValueP("user"); 757 if (pszUser) 758 RTStrCopy(pObjInfo->Attr.u.UnixOwner.szName, sizeof(pObjInfo->Attr.u.UnixOwner.szName), pszUser); 759 else 760 pObjInfo->Attr.u.UnixOwner.szName[0] = '\0'; 514 761 break; 762 } 515 763 516 764 case RTFSOBJATTRADD_UNIX_GROUP: 517 *pObjInfo = pThis->ObjInfo; 518 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP; 519 pObjInfo->Attr.u.UnixGroup.gid = pThis->ObjInfo.Attr.u.Unix.gid; 520 pObjInfo->Attr.u.UnixGroup.szName[0] = '\0'; 521 if (rtZipXarReaderHasGroupName(pThis->pXarReader)) 522 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), 523 pThis->pXarReader->Hdr.Common.gname); 765 { 766 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP; 767 if (RT_UNLIKELY(!pThis->pFileElem->getChildElementValueDefP("gid", 0, &pObjInfo->Attr.u.Unix.gid))) 768 return VERR_XAR_BAD_FILE_GID; 769 const char *pszGroup = pThis->pFileElem->findChildElementValueP("group"); 770 if (pszGroup) 771 RTStrCopy(pObjInfo->Attr.u.UnixGroup.szName, sizeof(pObjInfo->Attr.u.UnixGroup.szName), pszGroup); 772 else 773 pObjInfo->Attr.u.UnixGroup.szName[0] = '\0'; 524 774 break; 775 } 525 776 526 777 case RTFSOBJATTRADD_EASIZE: 527 *pObjInfo = pThis->ObjInfo;528 778 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE; 529 779 RT_ZERO(pObjInfo->Attr.u); … … 533 783 return VERR_NOT_SUPPORTED; 534 784 } 535 #endif536 785 537 786 return VINF_SUCCESS; … … 578 827 579 828 /** 580 * Reads one segment. 581 * 582 * @returns IPRT status code. 583 * @param pThis The instance data. 584 * @param pvBuf Where to put the read bytes. 585 * @param cbToRead The number of bytes to read. 586 * @param fBlocking Whether to block or not. 587 * @param pcbRead Where to store the number of bytes actually read. 588 */ 589 static int rtZipXarFssIos_ReadOneSeg(PRTZIPXARIOSTREAM pThis, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead) 590 { 591 /* 592 * Fend of reads beyond the end of the stream here. 593 */ 829 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 830 */ 831 static DECLCALLBACK(int) rtZipXarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 832 { 833 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 834 AssertReturn(off >= -1, VERR_INVALID_PARAMETER); 835 AssertReturn(pSgBuf->cSegs == 1, VERR_INVALID_PARAMETER); 836 837 /* 838 * Fend of reads beyond the end of the stream here. If 839 */ 840 if (off == -1) 841 off = pThis->offCurPos; 842 if (off < 0 || off > (RTFOFF)pThis->DataAttr.cbDataArchived) 843 return VERR_EOF; 594 844 if (pThis->fEndOfStream) 595 return pcbRead ? VINF_EOF : VERR_EOF; 596 597 Assert(pThis->Data.cbDataExtracted >= pThis->offFile); 598 uint64_t cbLeft = (uint64_t)(pThis->Data.cbDataExtracted - pThis->offFile); 845 { 846 if (off >= (RTFOFF)pThis->DataAttr.cbDataArchived) 847 return pcbRead ? VINF_EOF : VERR_EOF; 848 if (!pThis->fSeekable) 849 return VERR_SEEK_ON_DEVICE; 850 pThis->fEndOfStream = false; 851 } 852 853 size_t cbToRead = pSgBuf->paSegs[0].cbSeg; 854 uint64_t cbLeft = (uint64_t)(pThis->DataAttr.cbDataArchived - off); 599 855 if (cbToRead > cbLeft) 600 856 { … … 610 866 if (!pcbRead) 611 867 pcbRead = &cbReadStack; 612 int rc = RTVfsIoStrmRead(pThis->hVfsIos, pvBuf, cbToRead, fBlocking, pcbRead); 613 pThis->offFile += *pcbRead; 614 if (pThis->offFile >= pThis->Data.cbDataExtracted) 615 { 616 Assert(pThis->offFile == pThis->Data.cbDataExtracted); 868 int rc = RTVfsIoStrmReadAt(pThis->hVfsIos, off + pThis->DataAttr.offData, pSgBuf->paSegs[0].pvSeg, 869 cbToRead, fBlocking, pcbRead); 870 871 /* Feed the hashes. */ 872 size_t cbActuallyRead = *pcbRead; 873 if (pThis->uHashState == RTZIPXAR_HASH_PENDING) 874 { 875 if (pThis->offCurPos == pThis->cbDigested) 876 { 877 rtZipXarHashUpdate(&pThis->CtxArchived, pThis->DataAttr.uHashFunArchived, pSgBuf->paSegs[0].pvSeg, cbActuallyRead); 878 rtZipXarHashUpdate(&pThis->CtxExtracted, pThis->DataAttr.uHashFunExtracted, pSgBuf->paSegs[0].pvSeg, cbActuallyRead); 879 pThis->cbDigested += cbActuallyRead; 880 } 881 else if ( pThis->cbDigested > pThis->offCurPos 882 && pThis->cbDigested < (RTFOFF)(pThis->offCurPos + cbActuallyRead)) 883 { 884 size_t off = pThis->cbDigested - pThis->offCurPos; 885 void const *pvHash = (uint8_t const *)pSgBuf->paSegs[0].pvSeg + off; 886 size_t cbHash = cbActuallyRead - off; 887 rtZipXarHashUpdate(&pThis->CtxArchived, pThis->DataAttr.uHashFunArchived, pvHash, cbHash); 888 rtZipXarHashUpdate(&pThis->CtxExtracted, pThis->DataAttr.uHashFunExtracted, pvHash, cbHash); 889 pThis->cbDigested += cbHash; 890 } 891 } 892 893 /* Update the file position. */ 894 pThis->offCurPos += cbActuallyRead; 895 896 /* 897 * Check for end of stream, also check the hash. 898 */ 899 if (pThis->offCurPos >= (RTFOFF)pThis->DataAttr.cbDataArchived) 900 { 901 Assert(pThis->offCurPos == pThis->DataAttr.cbDataArchived); 617 902 pThis->fEndOfStream = true; 618 /// @todo RTVfsIoStrmSkip(pThis->hVfsIos, pThis->cbPadding); 619 } 620 621 return rc; 622 } 623 624 625 /** 626 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 627 */ 628 static DECLCALLBACK(int) rtZipXarFssIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 629 { 630 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 631 int rc; 632 AssertReturn(off == -1, VERR_INVALID_PARAMETER); 633 634 if (pSgBuf->cSegs == 1) 635 rc = rtZipXarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, fBlocking, pcbRead); 636 else 637 { 638 rc = VINF_SUCCESS; 639 size_t cbRead = 0; 640 size_t cbReadSeg; 641 size_t *pcbReadSeg = pcbRead ? &cbReadSeg : NULL; 642 for (uint32_t iSeg = 0; iSeg < pSgBuf->cSegs; iSeg++) 903 904 /* Check hash. */ 905 if ( pThis->uHashState == RTZIPXAR_HASH_PENDING 906 && pThis->cbDigested == pThis->DataAttr.cbDataArchived) 643 907 { 644 cbReadSeg = 0; 645 rc = rtZipXarFssIos_ReadOneSeg(pThis, pSgBuf->paSegs[iSeg].pvSeg, pSgBuf->paSegs[iSeg].cbSeg, fBlocking, pcbReadSeg); 646 if (RT_FAILURE(rc)) 647 break; 648 if (pcbRead) 908 RTZIPXARHASHDIGEST Digest; 909 rtZipXarHashFinal(&pThis->CtxArchived, pThis->DataAttr.uHashFunArchived, &Digest); 910 if (rtZipXarHashIsEqual(pThis->DataAttr.uHashFunArchived, &Digest, &pThis->DataAttr.DigestArchived)) 649 911 { 650 cbRead += cbReadSeg; 651 if (cbReadSeg != pSgBuf->paSegs[iSeg].cbSeg) 652 break; 912 rtZipXarHashFinal(&pThis->CtxExtracted, pThis->DataAttr.uHashFunExtracted, &Digest); 913 if (rtZipXarHashIsEqual(pThis->DataAttr.uHashFunExtracted, &Digest, &pThis->DataAttr.DigestExtracted)) 914 pThis->uHashState = RTZIPXAR_HASH_OK; 915 else 916 { 917 pThis->uHashState = RTZIPXAR_HASH_FAILED_EXTRACTED; 918 rc = VERR_XAR_EXTRACTED_HASH_MISMATCH; 919 } 920 } 921 else 922 { 923 pThis->uHashState = RTZIPXAR_HASH_FAILED_ARCHIVED; 924 rc = VERR_XAR_ARCHIVED_HASH_MISMATCH; 653 925 } 654 926 } 655 if (pcbRead) 656 *pcbRead = cbRead; 927 else if (pThis->uHashState == RTZIPXAR_HASH_FAILED_ARCHIVED) 928 rc = VERR_XAR_ARCHIVED_HASH_MISMATCH; 929 else if (pThis->uHashState == RTZIPXAR_HASH_FAILED_EXTRACTED) 930 rc = VERR_XAR_EXTRACTED_HASH_MISMATCH; 657 931 } 658 932 … … 713 987 { 714 988 PRTZIPXARIOSTREAM pThis = (PRTZIPXARIOSTREAM)pvThis; 715 *poffActual = pThis->off File;989 *poffActual = pThis->offCurPos; 716 990 return VINF_SUCCESS; 717 991 } … … 742 1016 RTVFSIOSTREAMOPS_VERSION 743 1017 }; 1018 1019 1020 /** 1021 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode} 1022 */ 1023 static DECLCALLBACK(int) rtZipXarFssFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask) 1024 { 1025 NOREF(pvThis); 1026 NOREF(fMode); 1027 NOREF(fMask); 1028 return VERR_NOT_SUPPORTED; 1029 } 1030 1031 1032 /** 1033 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes} 1034 */ 1035 static DECLCALLBACK(int) rtZipXarFssFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, 1036 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime) 1037 { 1038 NOREF(pvThis); 1039 NOREF(pAccessTime); 1040 NOREF(pModificationTime); 1041 NOREF(pChangeTime); 1042 NOREF(pBirthTime); 1043 return VERR_NOT_SUPPORTED; 1044 } 1045 1046 1047 /** 1048 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner} 1049 */ 1050 static DECLCALLBACK(int) rtZipXarFssFile_SetOwner(void *pvThis, RTUID uid, RTGID gid) 1051 { 1052 NOREF(pvThis); 1053 NOREF(uid); 1054 NOREF(gid); 1055 return VERR_NOT_SUPPORTED; 1056 } 1057 1058 1059 /** 1060 * @interface_method_impl{RTVFSFILEOPS,pfnSeek} 1061 */ 1062 static DECLCALLBACK(int) rtZipXarFssFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual) 1063 { 1064 PRTZIPXARFILE pThis = (PRTZIPXARFILE)pvThis; 1065 1066 /* Recalculate the request to RTFILE_SEEK_BEGIN. */ 1067 switch (uMethod) 1068 { 1069 case RTFILE_SEEK_BEGIN: 1070 break; 1071 case RTFILE_SEEK_CURRENT: 1072 offSeek += pThis->Ios.offCurPos; 1073 break; 1074 case RTFILE_SEEK_END: 1075 offSeek = pThis->Ios.DataAttr.cbDataArchived + offSeek; 1076 break; 1077 default: 1078 AssertFailedReturn(VERR_INVALID_PARAMETER); 1079 } 1080 1081 /* Do limit checks. */ 1082 if (offSeek < 0) 1083 offSeek = 0; 1084 else if (offSeek > (RTFOFF)pThis->Ios.DataAttr.cbDataArchived) 1085 offSeek = pThis->Ios.DataAttr.cbDataArchived; 1086 1087 /* Apply and return. */ 1088 pThis->Ios.fEndOfStream = (offSeek >= (RTFOFF)pThis->Ios.DataAttr.cbDataArchived); 1089 pThis->Ios.offCurPos = offSeek; 1090 if (poffActual) 1091 *poffActual = offSeek; 1092 1093 return VINF_SUCCESS; 1094 } 1095 1096 1097 /** 1098 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize} 1099 */ 1100 static DECLCALLBACK(int) rtZipXarFssFile_QuerySize(void *pvThis, uint64_t *pcbFile) 1101 { 1102 PRTZIPXARFILE pThis = (PRTZIPXARFILE)pvThis; 1103 *pcbFile = pThis->Ios.DataAttr.cbDataArchived; 1104 return VINF_SUCCESS; 1105 } 1106 1107 1108 /** 1109 * Xar file operations. 1110 */ 1111 static const RTVFSFILEOPS g_rtZipXarFssFileOps = 1112 { 1113 { /* I/O stream */ 1114 { /* Obj */ 1115 RTVFSOBJOPS_VERSION, 1116 RTVFSOBJTYPE_FILE, 1117 "XarFsStream::File", 1118 rtZipXarFssIos_Close, 1119 rtZipXarFssIos_QueryInfo, 1120 RTVFSOBJOPS_VERSION 1121 }, 1122 RTVFSIOSTREAMOPS_VERSION, 1123 RTVFSIOSTREAMOPS_FEAT_NO_SG, 1124 rtZipXarFssIos_Read, 1125 rtZipXarFssIos_Write, 1126 rtZipXarFssIos_Flush, 1127 rtZipXarFssIos_PollOne, 1128 rtZipXarFssIos_Tell, 1129 NULL /*Skip*/, 1130 NULL /*ZeroFill*/, 1131 RTVFSIOSTREAMOPS_VERSION 1132 }, 1133 RTVFSFILEOPS_VERSION, 1134 0, 1135 { /* ObjSet */ 1136 RTVFSOBJSETOPS_VERSION, 1137 RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet), 1138 rtZipXarFssFile_SetMode, 1139 rtZipXarFssFile_SetTimes, 1140 rtZipXarFssFile_SetOwner, 1141 RTVFSOBJSETOPS_VERSION 1142 }, 1143 rtZipXarFssFile_Seek, 1144 rtZipXarFssFile_QuerySize, 1145 RTVFSFILEOPS_VERSION, 1146 }; 1147 1148 1149 1150 1151 /** 1152 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 1153 */ 1154 static DECLCALLBACK(int) rtZipXarFssDecompIos_Close(void *pvThis) 1155 { 1156 PRTZIPXARDECOMPIOS pThis = (PRTZIPXARDECOMPIOS)pvThis; 1157 1158 RTVfsIoStrmRelease(pThis->hVfsIosDecompressor); 1159 pThis->hVfsIosDecompressor = NIL_RTVFSIOSTREAM; 1160 1161 int rc = RTVfsIoStrmRelease(pThis->hVfsIosRaw); 1162 pThis->hVfsIosRaw = NIL_RTVFSIOSTREAM; 1163 pThis->pIosRaw = NULL; 1164 1165 return rc; 1166 } 1167 1168 1169 /** 1170 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 1171 */ 1172 static DECLCALLBACK(int) rtZipXarFssDecompIos_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 1173 { 1174 PRTZIPXARDECOMPIOS pThis = (PRTZIPXARDECOMPIOS)pvThis; 1175 1176 int rc = rtZipXarFssBaseObj_QueryInfo(&pThis->pIosRaw->BaseObj, pObjInfo, enmAddAttr); 1177 pObjInfo->cbObject = pThis->pIosRaw->DataAttr.cbDataExtracted; 1178 return rc; 1179 } 1180 1181 1182 /** 1183 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 1184 */ 1185 static DECLCALLBACK(int) rtZipXarFssDecompIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 1186 { 1187 PRTZIPXARDECOMPIOS pThis = (PRTZIPXARDECOMPIOS)pvThis; 1188 AssertReturn(pSgBuf->cSegs == 1, VERR_INVALID_PARAMETER); 1189 1190 /* 1191 * Enforce the cbDataExtracted limit. 1192 */ 1193 if (pThis->offCurPos > (RTFOFF)pThis->pIosRaw->DataAttr.cbDataExtracted) 1194 return VERR_XAR_EXTRACTED_SIZE_EXCEEDED; 1195 1196 /* 1197 * Read the data. 1198 * 1199 * ASSUMES the decompressor stream isn't seekable, so we don't have to 1200 * validate off wrt data digest updating. 1201 */ 1202 int rc = RTVfsIoStrmReadAt(pThis->hVfsIosDecompressor, off, pSgBuf->paSegs[0].pvSeg, pSgBuf->paSegs[0].cbSeg, 1203 fBlocking, pcbRead); 1204 if (RT_FAILURE(rc)) 1205 return rc; 1206 1207 /* 1208 * Hash the data. When reaching the end match against the expected digest. 1209 */ 1210 size_t cbActuallyRead = pcbRead ? *pcbRead : pSgBuf->paSegs[0].cbSeg; 1211 pThis->offCurPos += cbActuallyRead; 1212 rtZipXarHashUpdate(&pThis->CtxExtracted, pThis->uHashFunExtracted, pSgBuf->paSegs[0].pvSeg, cbActuallyRead); 1213 if (rc == VINF_EOF) 1214 { 1215 if (pThis->offCurPos == (RTFOFF)pThis->pIosRaw->DataAttr.cbDataExtracted) 1216 { 1217 if (pThis->uHashState == RTZIPXAR_HASH_PENDING) 1218 { 1219 RTZIPXARHASHDIGEST Digest; 1220 rtZipXarHashFinal(&pThis->CtxExtracted, pThis->uHashFunExtracted, &Digest); 1221 if (rtZipXarHashIsEqual(pThis->uHashFunExtracted, &Digest, &pThis->DigestExtracted)) 1222 pThis->uHashState = RTZIPXAR_HASH_OK; 1223 else 1224 { 1225 pThis->uHashState = RTZIPXAR_HASH_FAILED_EXTRACTED; 1226 rc = VERR_XAR_EXTRACTED_HASH_MISMATCH; 1227 } 1228 } 1229 else if (pThis->uHashState != RTZIPXAR_HASH_OK) 1230 rc = VERR_XAR_EXTRACTED_HASH_MISMATCH; 1231 } 1232 else 1233 rc = VERR_XAR_EXTRACTED_SIZE_EXCEEDED; 1234 1235 /* Ensure that the raw stream is also at the end so that both 1236 message digests are checked. */ 1237 if (RT_SUCCESS(rc)) 1238 { 1239 if ( pThis->pIosRaw->offCurPos < (RTFOFF)pThis->pIosRaw->DataAttr.cbDataArchived 1240 || pThis->pIosRaw->uHashState == RTZIPXAR_HASH_PENDING) 1241 rc = VERR_XAR_UNUSED_ARCHIVED_DATA; 1242 else if (pThis->pIosRaw->uHashState != RTZIPXAR_HASH_OK) 1243 rc = VERR_XAR_ARCHIVED_HASH_MISMATCH; 1244 } 1245 } 1246 1247 return rc; 1248 } 1249 1250 1251 /** 1252 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite} 1253 */ 1254 static DECLCALLBACK(int) rtZipXarFssDecompIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten) 1255 { 1256 /* Cannot write to a read-only I/O stream. */ 1257 NOREF(pvThis); NOREF(off); NOREF(pSgBuf); NOREF(fBlocking); NOREF(pcbWritten); 1258 return VERR_ACCESS_DENIED; 1259 } 1260 1261 1262 /** 1263 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush} 1264 */ 1265 static DECLCALLBACK(int) rtZipXarFssDecompIos_Flush(void *pvThis) 1266 { 1267 /* It's a read only stream, nothing dirty to flush. */ 1268 NOREF(pvThis); 1269 return VINF_SUCCESS; 1270 } 1271 1272 1273 /** 1274 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnPollOne} 1275 */ 1276 static DECLCALLBACK(int) rtZipXarFssDecompIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, 1277 uint32_t *pfRetEvents) 1278 { 1279 PRTZIPXARDECOMPIOS pThis = (PRTZIPXARDECOMPIOS)pvThis; 1280 return RTVfsIoStrmPoll(pThis->hVfsIosDecompressor, fEvents, cMillies, fIntr, pfRetEvents); 1281 } 1282 1283 1284 /** 1285 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell} 1286 */ 1287 static DECLCALLBACK(int) rtZipXarFssDecompIos_Tell(void *pvThis, PRTFOFF poffActual) 1288 { 1289 PRTZIPXARDECOMPIOS pThis = (PRTZIPXARDECOMPIOS)pvThis; 1290 *poffActual = pThis->offCurPos; 1291 return VINF_SUCCESS; 1292 } 1293 1294 1295 /** 1296 * Xar I/O stream operations. 1297 */ 1298 static const RTVFSIOSTREAMOPS g_rtZipXarFssDecompIosOps = 1299 { 1300 { /* Obj */ 1301 RTVFSOBJOPS_VERSION, 1302 RTVFSOBJTYPE_IO_STREAM, 1303 "XarFsStream::DecompIoStream", 1304 rtZipXarFssDecompIos_Close, 1305 rtZipXarFssDecompIos_QueryInfo, 1306 RTVFSOBJOPS_VERSION 1307 }, 1308 RTVFSIOSTREAMOPS_VERSION, 1309 0, 1310 rtZipXarFssDecompIos_Read, 1311 rtZipXarFssDecompIos_Write, 1312 rtZipXarFssDecompIos_Flush, 1313 rtZipXarFssDecompIos_PollOne, 1314 rtZipXarFssDecompIos_Tell, 1315 NULL /*Skip*/, 1316 NULL /*ZeroFill*/, 1317 RTVFSIOSTREAMOPS_VERSION 1318 }; 1319 1320 744 1321 745 1322 … … 843 1420 PRTZIPXARFSSTREAM pThis = (PRTZIPXARFSSTREAM)pvThis; 844 1421 845 RTVfsObjRelease(pThis->hVfsCurObj);846 pThis->hVfsCurObj = NIL_RTVFSOBJ;847 pThis->pCurIosData = NULL;848 849 1422 RTVfsIoStrmRelease(pThis->hVfsIos); 850 1423 pThis->hVfsIos = NIL_RTVFSIOSTREAM; … … 869 1442 870 1443 871 static xml::ElementNode const *rtZipXarGetNextFileElement(xml::ElementNode const *pCurFile, uint32_t *pcCurDepth)872 {873 /*874 * Consider children first.875 */876 xml::ElementNode const *pChild = pCurFile->findChildElement("file");877 if (pChild)878 {879 *pcCurDepth += 1;880 return pChild;881 }882 883 /*884 * Then siblings.885 */886 xml::ElementNode const *pSibling = pCurFile->findNextSibilingElement("file");887 if (pSibling != NULL)888 return pSibling;889 890 /*891 * Ascend and see if some parent has more siblings.892 */893 while (*pcCurDepth > 0)894 {895 pCurFile = static_cast<const xml::ElementNode *>(pCurFile->getParent());896 AssertBreak(pCurFile);897 Assert(pCurFile->nameEquals("file"));898 *pcCurDepth -= 1;899 900 pSibling = pCurFile->findNextSibilingElement("file");901 if (pSibling != NULL)902 return pSibling;903 }904 905 return NULL;906 }907 908 909 1444 /** 910 1445 * @interface_method_impl{RTVFSFSSTREAMOPS,pfnNext} … … 913 1448 { 914 1449 PRTZIPXARFSSTREAM pThis = (PRTZIPXARFSSTREAM)pvThis; 915 916 /*917 * Dispense with the current object.918 */919 if (pThis->hVfsCurObj != NIL_RTVFSOBJ)920 {921 if (pThis->pCurIosData)922 {923 pThis->pCurIosData->fEndOfStream = true;924 /// @todo pThis->pCurIosData->offFile = pThis->pCurIosData->cbFile;925 pThis->pCurIosData = NULL;926 }927 928 RTVfsObjRelease(pThis->hVfsCurObj);929 pThis->hVfsCurObj = NIL_RTVFSOBJ;930 }931 1450 932 1451 /* … … 941 1460 * Get the next file element. 942 1461 */ 943 if (pThis->XarReader.fFirstFile) 944 { 945 pThis->XarReader.pCurFile = pThis->XarReader.pToc->findChildElement("file"); 946 pThis->XarReader.cCurDepth = 0; 947 } 948 else if (pThis->XarReader.pCurFile) 949 pThis->XarReader.pCurFile = rtZipXarGetNextFileElement(pThis->XarReader.pCurFile, &pThis->XarReader.cCurDepth); 950 if (!pThis->XarReader.pCurFile) 1462 xml::ElementNode const *pCurFile = pThis->XarReader.pCurFile; 1463 if (pCurFile) 1464 pThis->XarReader.pCurFile = pCurFile = rtZipXarGetNextFileElement(pCurFile, &pThis->XarReader.cCurDepth); 1465 else if (!pThis->fEndOfStream) 1466 { 1467 pThis->XarReader.cCurDepth = 0; 1468 pThis->XarReader.pCurFile = pCurFile = pThis->XarReader.pToc->findChildElement("file"); 1469 } 1470 if (!pCurFile) 951 1471 { 952 1472 pThis->fEndOfStream = true; … … 957 1477 * Retrive the fundamental attributes (elements actually). 958 1478 */ 959 const char *pszName = p This->XarReader.pCurFile->findChildElementValueP("name");960 const char *pszType = p This->XarReader.pCurFile->findChildElementValueP("type");1479 const char *pszName = pCurFile->findChildElementValueP("name"); 1480 const char *pszType = pCurFile->findChildElementValueP("type"); 961 1481 if (RT_UNLIKELY(!pszName || !pszType)) 962 1482 return pThis->rcFatal = VERR_XAR_BAD_FILE_ELEMENT; 1483 1484 /* 1485 * Validate the filename. Being a little too paranoid here, perhaps, wrt 1486 * path separators and escapes... 1487 */ 1488 if ( !*pszName 1489 || strchr(pszName, '/') 1490 || strchr(pszName, '\\') 1491 || strchr(pszName, ':') 1492 || !strcmp(pszName, "..") ) 1493 return pThis->rcFatal = VERR_XAR_INVALID_FILE_NAME; 963 1494 964 1495 /* … … 971 1502 if (!strcmp(pszType, "file")) 972 1503 { 973 #if 0 /// @todo continue hacking here 974 rc = rtZipXarGetDataStreamAttributes(p This->XarReader.pCurFile, &offData, &cbData);1504 RTZIPXARDATASTREAM DataAttr; 1505 rc = rtZipXarGetDataStreamAttributes(pCurFile, &DataAttr); 975 1506 if (RT_FAILURE(rc)) 976 1507 return pThis->rcFatal = rc; 977 978 979 if (pThis->hVfsFile != NIL_RTVFSFILE) 1508 DataAttr.offData += pThis->offZero + pThis->offStart; 1509 1510 if ( pThis->hVfsFile != NIL_RTVFSFILE 1511 && DataAttr.enmEncoding == RTZIPXARENCODING_STORE) 980 1512 { 981 1513 /* 1514 * The input is seekable and the XAR file isn't compressed, so we 1515 * can provide a seekable file to the user. 1516 */ 1517 RTVFSFILE hVfsFile; 1518 PRTZIPXARFILE pFileData; 1519 rc = RTVfsNewFile(&g_rtZipXarFssFileOps, 1520 sizeof(*pFileData), 1521 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, 1522 NIL_RTVFS, 1523 NIL_RTVFSLOCK, 1524 &hVfsFile, 1525 (void **)&pFileData); 1526 if (RT_FAILURE(rc)) 1527 return pThis->rcFatal = rc; 1528 1529 pFileData->Ios.BaseObj.pFileElem = pCurFile; 1530 pFileData->Ios.BaseObj.fModeType = RTFS_TYPE_FILE; 1531 pFileData->Ios.DataAttr = DataAttr; 1532 pFileData->Ios.offCurPos = 0; 1533 pFileData->Ios.fEndOfStream = false; 1534 pFileData->Ios.fSeekable = true; 1535 pFileData->Ios.uHashState = RTZIPXAR_HASH_PENDING; 1536 pFileData->Ios.cbDigested = 0; 1537 rtZipXarHashInit(&pFileData->Ios.CtxArchived, pFileData->Ios.DataAttr.uHashFunArchived); 1538 rtZipXarHashInit(&pFileData->Ios.CtxExtracted, pFileData->Ios.DataAttr.uHashFunExtracted); 1539 1540 pFileData->Ios.hVfsIos = pThis->hVfsIos; 1541 RTVfsIoStrmRetain(pFileData->Ios.hVfsIos); 1542 pFileData->hVfsFile = pThis->hVfsFile; 1543 RTVfsFileRetain(pFileData->hVfsFile); 1544 1545 /* Try avoid double content hashing. */ 1546 if (pFileData->Ios.DataAttr.uHashFunArchived == pFileData->Ios.DataAttr.uHashFunExtracted) 1547 pFileData->Ios.DataAttr.uHashFunExtracted = XAR_HASH_NONE; 1548 1549 enmType = RTVFSOBJTYPE_FILE; 1550 hVfsObj = RTVfsObjFromFile(hVfsFile); 1551 RTVfsFileRelease(hVfsFile); 982 1552 } 983 1553 else 984 1554 { 985 RTVFSIOSTREAM hVfsIos ;1555 RTVFSIOSTREAM hVfsIosRaw; 986 1556 PRTZIPXARIOSTREAM pIosData; 987 1557 rc = RTVfsNewIoStream(&g_rtZipXarFssIosOps, … … 990 1560 NIL_RTVFS, 991 1561 NIL_RTVFSLOCK, 992 &hVfsIos ,1562 &hVfsIosRaw, 993 1563 (void **)&pIosData); 994 1564 if (RT_FAILURE(rc)) 995 1565 return pThis->rcFatal = rc; 996 1566 997 pIosData->BaseObj.pXarReader = &pThis->XarReader; 998 pIosData->BaseObj.pFileElem = pThis->XarReader.pCurFile; 999 pIosData->cbFile = cbData; 1000 pIosData->offFile = 0; 1001 pIosData->cbPadding = (uint32_t)(Info.cbAllocated - Info.cbObject); 1002 pIosData->fEndOfStream = false; 1003 pIosData->hVfsIos = pThis->hVfsIos; 1567 pIosData->BaseObj.pFileElem = pCurFile; 1568 pIosData->BaseObj.fModeType = RTFS_TYPE_FILE; 1569 pIosData->DataAttr = DataAttr; 1570 pIosData->offCurPos = 0; 1571 pIosData->fEndOfStream = false; 1572 pIosData->fSeekable = pThis->hVfsFile != NIL_RTVFSFILE; 1573 pIosData->uHashState = RTZIPXAR_HASH_PENDING; 1574 pIosData->cbDigested = 0; 1575 rtZipXarHashInit(&pIosData->CtxArchived, pIosData->DataAttr.uHashFunArchived); 1576 rtZipXarHashInit(&pIosData->CtxExtracted, pIosData->DataAttr.uHashFunExtracted); 1577 1578 pIosData->hVfsIos = pThis->hVfsIos; 1004 1579 RTVfsIoStrmRetain(pThis->hVfsIos); 1005 1580 1006 pThis->pCurIosData = pIosData; 1007 pThis->offNextHdr += pIosData->cbFile + pIosData->cbPadding; 1008 1581 if ( pIosData->DataAttr.enmEncoding != RTZIPXARENCODING_STORE 1582 && pIosData->DataAttr.enmEncoding != RTZIPXARENCODING_UNSUPPORTED) 1583 { 1584 /* 1585 * We need to set up a decompression chain. 1586 */ 1587 RTVFSIOSTREAM hVfsIosDecomp; 1588 PRTZIPXARDECOMPIOS pIosDecompData; 1589 rc = RTVfsNewIoStream(&g_rtZipXarFssDecompIosOps, 1590 sizeof(*pIosDecompData), 1591 RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, 1592 NIL_RTVFS, 1593 NIL_RTVFSLOCK, 1594 &hVfsIosDecomp, 1595 (void **)&pIosDecompData); 1596 if (RT_FAILURE(rc)) 1597 { 1598 RTVfsIoStrmRelease(hVfsIosRaw); 1599 return pThis->rcFatal = rc; 1600 } 1601 1602 pIosDecompData->hVfsIosDecompressor = NIL_RTVFSIOSTREAM; 1603 pIosDecompData->hVfsIosRaw = hVfsIosRaw; 1604 pIosDecompData->pIosRaw = pIosData; 1605 pIosDecompData->offCurPos = 0; 1606 pIosDecompData->uHashFunExtracted = DataAttr.uHashFunExtracted; 1607 pIosDecompData->uHashState = RTZIPXAR_HASH_PENDING; 1608 rtZipXarHashInit(&pIosDecompData->CtxExtracted, pIosDecompData->uHashFunExtracted); 1609 pIosDecompData->DigestExtracted = DataAttr.DigestExtracted; 1610 1611 /* Tell the raw end to only hash the archived data. */ 1612 pIosData->DataAttr.uHashFunExtracted = XAR_HASH_NONE; 1613 1614 /* 1615 * Hook up the decompressor. 1616 */ 1617 switch (DataAttr.enmEncoding) 1618 { 1619 case RTZIPXARENCODING_GZIP: 1620 /* Must allow zlib header, all examples I've got seems 1621 to be using it rather than the gzip one. Makes 1622 sense as there is no need to repeat the file name 1623 and the attributes. */ 1624 rc = RTZipGzipDecompressIoStream(hVfsIosRaw, RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR, 1625 &pIosDecompData->hVfsIosDecompressor); 1626 break; 1627 default: 1628 rc = VERR_INTERNAL_ERROR_5; 1629 break; 1630 } 1631 if (RT_FAILURE(rc)) 1632 { 1633 RTVfsIoStrmRelease(hVfsIosDecomp); 1634 return pThis->rcFatal = rc; 1635 } 1636 1637 /* What to return. */ 1638 hVfsObj = RTVfsObjFromIoStream(hVfsIosDecomp); 1639 RTVfsIoStrmRelease(hVfsIosDecomp); 1640 } 1641 else 1642 { 1643 /* Try avoid double content hashing. */ 1644 if (pIosData->DataAttr.uHashFunArchived == pIosData->DataAttr.uHashFunExtracted) 1645 pIosData->DataAttr.uHashFunExtracted = XAR_HASH_NONE; 1646 1647 /* What to return. */ 1648 hVfsObj = RTVfsObjFromIoStream(hVfsIosRaw); 1649 RTVfsIoStrmRelease(hVfsIosRaw); 1650 } 1009 1651 enmType = RTVFSOBJTYPE_IO_STREAM; 1010 hVfsObj = RTVfsObjFromIoStream(hVfsIos);1011 RTVfsIoStrmRelease(hVfsIos);1012 1652 } 1013 #endif1014 1653 } 1015 1654 else if (!strcmp(pszType, "directory")) … … 1025 1664 return pThis->rcFatal = rc; 1026 1665 1027 pBaseObjData->p XarReader = &pThis->XarReader;1028 pBaseObjData-> pFileElem = pThis->XarReader.pCurFile;1666 pBaseObjData->pFileElem = pCurFile; 1667 pBaseObjData->fModeType = RTFS_TYPE_DIRECTORY; 1029 1668 1030 1669 enmType = RTVFSOBJTYPE_BASE; 1031 1670 } 1032 else 1033 return pThis->rcFatal = VERR_XAR_BAD_UNKNOWN_FILE_TYPE; 1034 1035 #if 0 1036 /* 1037 * Consume XAR headers. 1038 */ 1039 size_t cbHdrs = 0; 1040 int rc; 1041 do 1042 { 1043 /* 1044 * Read the next header. 1045 */ 1046 RTZIPXARHDR Hdr; 1047 size_t cbRead; 1048 rc = RTVfsIoStrmRead(pThis->hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, &cbRead); 1671 else if (!strcmp(pszType, "symlink")) 1672 { 1673 RTVFSSYMLINK hVfsSym; 1674 PRTZIPXARBASEOBJ pBaseObjData; 1675 rc = RTVfsNewSymlink(&g_rtZipXarFssSymOps, 1676 sizeof(*pBaseObjData), 1677 NIL_RTVFS, 1678 NIL_RTVFSLOCK, 1679 &hVfsSym, 1680 (void **)&pBaseObjData); 1049 1681 if (RT_FAILURE(rc)) 1050 1682 return pThis->rcFatal = rc; 1051 if (rc == VINF_EOF && cbRead == 0) 1683 1684 pBaseObjData->pFileElem = pCurFile; 1685 pBaseObjData->fModeType = RTFS_TYPE_SYMLINK; 1686 1687 enmType = RTVFSOBJTYPE_SYMLINK; 1688 hVfsObj = RTVfsObjFromSymlink(hVfsSym); 1689 RTVfsSymlinkRelease(hVfsSym); 1690 } 1691 else 1692 return pThis->rcFatal = VERR_XAR_UNKNOWN_FILE_TYPE; 1693 1694 /* 1695 * Set the return data and we're done. 1696 */ 1697 if (ppszName) 1698 { 1699 /* Figure the length. */ 1700 size_t const cbCurName = strlen(pszName) + 1; 1701 size_t cbFullName = cbCurName; 1702 const xml::ElementNode *pAncestor = pCurFile; 1703 uint32_t cLeft = pThis->XarReader.cCurDepth; 1704 while (cLeft-- > 0) 1052 1705 { 1053 pThis->fEndOfStream = true; 1054 return rtZipXarReaderIsAtEnd(&pThis->XarReader) ? VERR_EOF : VERR_XAR_UNEXPECTED_EOS; 1706 pAncestor = (const xml::ElementNode *)pAncestor->getParent(); Assert(pAncestor); 1707 const char *pszAncestorName = pAncestor->findChildElementValueP("name"); Assert(pszAncestorName); 1708 cbFullName += strlen(pszAncestorName) + 1; 1055 1709 } 1056 if (cbRead != sizeof(Hdr)) 1057 return pThis->rcFatal = VERR_XAR_UNEXPECTED_EOS; 1058 1059 cbHdrs += sizeof(Hdr); 1060 1061 /* 1062 * Parse the it. 1063 */ 1064 rc = rtZipXarReaderParseHeader(&pThis->XarReader, &Hdr); 1065 if (RT_FAILURE(rc)) 1066 return pThis->rcFatal = rc; 1067 } while (rtZipXarReaderExpectingMoreHeaders(&pThis->XarReader)); 1068 1069 pThis->offNextHdr = offHdr + cbHdrs; 1070 1071 /* 1072 * Fill an object info structure from the current XAR state. 1073 */ 1074 RTFSOBJINFO Info; 1075 rc = rtZipXarReaderGetFsObjInfo(&pThis->XarReader, &Info); 1076 if (RT_FAILURE(rc)) 1077 return pThis->rcFatal = rc; 1078 1079 /* 1080 * Create an object of the appropriate type. 1081 */ 1082 RTVFSOBJTYPE enmType; 1083 RTVFSOBJ hVfsObj; 1084 RTFMODE fType = Info.Attr.fMode & RTFS_TYPE_MASK; 1085 if (rtZipXarReaderIsHardlink(&pThis->XarReader)) 1086 fType = RTFS_TYPE_SYMLINK; 1087 switch (fType) 1088 { 1089 /* 1090 * Files are represented by a VFS I/O stream. 1091 */ 1092 case RTFS_TYPE_FILE: 1710 1711 /* Allocate a buffer. */ 1712 char *psz = *ppszName = RTStrAlloc(cbFullName); 1713 if (!psz) 1093 1714 { 1094 break; 1715 RTVfsObjRelease(hVfsObj); 1716 return VERR_NO_STR_MEMORY; 1095 1717 } 1096 1718 1097 /* 1098 * We represent hard links using a symbolic link object. This fits 1099 * best with the way XAR stores it and there is currently no better 1100 * fitting VFS type alternative. 1101 */ 1102 case RTFS_TYPE_SYMLINK: 1719 /* Construct it, from the end. */ 1720 psz += cbFullName; 1721 psz -= cbCurName; 1722 memcpy(psz, pszName, cbCurName); 1723 1724 pAncestor = pCurFile; 1725 cLeft = pThis->XarReader.cCurDepth; 1726 while (cLeft-- > 0) 1103 1727 { 1104 RTVFSSYMLINK hVfsSym; 1105 PRTZIPXARBASEOBJ pBaseObjData; 1106 rc = RTVfsNewSymlink(&g_rtZipXarFssSymOps, 1107 sizeof(*pBaseObjData), 1108 NIL_RTVFS, 1109 NIL_RTVFSLOCK, 1110 &hVfsSym, 1111 (void **)&pBaseObjData); 1112 if (RT_FAILURE(rc)) 1113 return pThis->rcFatal = rc; 1114 1115 pBaseObjData->offHdr = offHdr; 1116 pBaseObjData->pXarReader= &pThis->XarReader; 1117 pBaseObjData->ObjInfo = Info; 1118 1119 enmType = RTVFSOBJTYPE_SYMLINK; 1120 hVfsObj = RTVfsObjFromSymlink(hVfsSym); 1121 RTVfsSymlinkRelease(hVfsSym); 1122 break; 1728 pAncestor = (const xml::ElementNode *)pAncestor->getParent(); Assert(pAncestor); 1729 const char *pszAncestorName = pAncestor->findChildElementValueP("name"); Assert(pszAncestorName); 1730 *--psz = '/'; 1731 size_t cchAncestorName = strlen(pszAncestorName); 1732 psz -= cchAncestorName; 1733 memcpy(psz, pszAncestorName, cchAncestorName); 1123 1734 } 1124 1125 /* 1126 * All other objects are repesented using a VFS base object since they 1127 * carry no data streams (unless some XAR extension implements extended 1128 * attributes / alternative streams). 1129 */ 1130 case RTFS_TYPE_DEV_BLOCK: 1131 case RTFS_TYPE_DEV_CHAR: 1132 case RTFS_TYPE_DIRECTORY: 1133 case RTFS_TYPE_FIFO: 1134 { 1135 PRTZIPXARBASEOBJ pBaseObjData; 1136 rc = RTVfsNewBaseObj(&g_rtZipXarFssBaseObjOps, 1137 sizeof(*pBaseObjData), 1138 NIL_RTVFS, 1139 NIL_RTVFSLOCK, 1140 &hVfsObj, 1141 (void **)&pBaseObjData); 1142 if (RT_FAILURE(rc)) 1143 return pThis->rcFatal = rc; 1144 1145 pBaseObjData->offHdr = offHdr; 1146 pBaseObjData->pXarReader= &pThis->XarReader; 1147 pBaseObjData->ObjInfo = Info; 1148 1149 enmType = RTVFSOBJTYPE_BASE; 1150 break; 1151 } 1152 1153 default: 1154 AssertFailed(); 1155 return pThis->rcFatal = VERR_INTERNAL_ERROR_5; 1156 } 1157 pThis->hVfsCurObj = hVfsObj; 1158 #endif 1159 1160 /* 1161 * Set the return data and we're done. 1162 */ 1163 if (ppszName) 1164 { 1165 rc = RTStrDupEx(ppszName, pszName); /** @todo fixme */ 1166 if (RT_FAILURE(rc)) 1167 return rc; 1735 Assert(*ppszName == psz); 1168 1736 } 1169 1737 … … 1232 1800 1233 1801 uint8_t uHashFunction; 1234 if (!strcmp(pszStyle, "sha1")) 1235 uHashFunction = XAR_HASH_SHA1; 1236 else if (!strcmp(pszStyle, "md5")) 1237 uHashFunction = XAR_HASH_MD5; 1238 else if (!strcmp(pszStyle, "none")) 1239 uHashFunction = XAR_HASH_NONE; 1240 else 1241 return VERR_XAR_BAD_CHECKSUM_ELEMENT; 1802 rc = rtZipXarParseChecksumStyle(pszStyle, &uHashFunction); 1803 if (RT_FAILURE(rc)) 1804 return rc; 1242 1805 if (uHashFunction != pThis->uHashFunction) 1243 1806 return VERR_XAR_HASH_FUNCTION_MISMATCH; … … 1250 1813 RTFOFF offChecksum; 1251 1814 uint64_t cbChecksum; 1252 rc = rtZipXarGetOffsetSize FromElem(pChecksumElem, &offChecksum, &cbChecksum);1815 rc = rtZipXarGetOffsetSizeLengthFromElem(pChecksumElem, &offChecksum, &cbChecksum, NULL); 1253 1816 if (RT_FAILURE(rc)) 1254 1817 return rc; … … 1490 2053 pThis->hVfsIos = hVfsIosIn; 1491 2054 pThis->hVfsFile = RTVfsIoStrmToFile(hVfsIosIn); 1492 pThis->hVfsCurObj = NIL_RTVFSOBJ;1493 pThis->pCurIosData = NULL;1494 2055 pThis->offStart = offStart; 1495 2056 pThis->offZero = offZero; … … 1507 2068 pThis->XarReader.pCurFile = 0; 1508 2069 pThis->XarReader.cCurDepth = 0; 1509 pThis->XarReader.fFirstFile = true;1510 2070 1511 2071 /*
Note:
See TracChangeset
for help on using the changeset viewer.