Changeset 67568 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jun 22, 2017 4:24:56 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/iso9660vfs.cpp
r67559 r67568 417 417 * properly initialized elsewhere. 418 418 * 419 * @returns IRPT status code. Either VINF_SUCCESS or VERR_NO_MEMORY, the latter 420 * only if @a cDirRecs is above 1. 419 421 * @param pCore The structure to initialize. 420 422 * @param pDirRec The primary directory record. … … 424 426 * @param pVol The volume. 425 427 */ 426 static voidrtFsIso9660Core_InitFromDirRec(PRTFSISO9660CORE pCore, PCISO9660DIRREC pDirRec, uint32_t cDirRecs,427 428 static int rtFsIso9660Core_InitFromDirRec(PRTFSISO9660CORE pCore, PCISO9660DIRREC pDirRec, uint32_t cDirRecs, 429 uint64_t offDirRec, uint32_t uVersion, PRTFSISO9660VOL pVol) 428 430 { 429 431 Assert(cDirRecs == 1); RT_NOREF(cDirRecs); … … 448 450 pCore->AccessTime = pCore->ModificationTime; 449 451 pCore->ChangeTime = pCore->ModificationTime; 452 453 /* 454 * Deal with multiple extents. 455 */ 456 if (RT_LIKELY(cDirRecs == 1)) 457 { /* done */ } 458 else 459 { 460 PRTFSISO9660EXTENT pCurExtent = &pCore->FirstExtent; 461 while (cDirRecs > 1) 462 { 463 offDirRec += pDirRec->cbDirRec; 464 pDirRec = (PCISO9660DIRREC)((uintptr_t)pDirRec + pDirRec->cbDirRec); 465 if (pDirRec->cbDirRec != 0) 466 { 467 uint64_t offDisk = ISO9660_GET_ENDIAN(&pDirRec->offExtent) * (uint64_t)pVol->cbBlock; 468 uint32_t cbExtent = ISO9660_GET_ENDIAN(&pDirRec->cbData); 469 pCore->cbObject += cbExtent; 470 471 if (pCurExtent->offDisk + pCurExtent->cbExtent == offDisk) 472 pCurExtent->cbExtent += cbExtent; 473 else 474 { 475 void *pvNew = RTMemRealloc(pCore->paExtents, pCore->cExtents * sizeof(pCore->paExtents[0])); 476 if (pvNew) 477 pCore->paExtents = (PRTFSISO9660EXTENT)pvNew; 478 else 479 { 480 RTMemFree(pCore->paExtents); 481 return VERR_NO_MEMORY; 482 } 483 pCurExtent = &pCore->paExtents[pCore->cExtents - 1]; 484 pCurExtent->cbExtent = cbExtent; 485 pCurExtent->offDisk = offDisk; 486 pCore->cExtents++; 487 } 488 cDirRecs--; 489 } 490 else 491 { 492 size_t cbSkip = (offDirRec + pVol->cbSector) & ~(pVol->cbSector - 1U); 493 offDirRec += cbSkip; 494 pDirRec = (PCISO9660DIRREC)((uintptr_t)pDirRec + cbSkip); 495 } 496 } 497 } 498 return VINF_SUCCESS; 450 499 } 451 500 … … 836 885 * Initialize it all so rtFsIso9660File_Close doesn't trip up in anyway. 837 886 */ 838 rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, uVersion, pThis); 839 rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core); 887 rc = rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, uVersion, pThis); 888 if (RT_SUCCESS(rc)) 889 rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core); 890 else 891 { 892 RTMemFree(pShared); 893 pShared = NULL; 894 } 840 895 } 841 896 } … … 876 931 } 877 932 return NULL; 933 } 934 935 936 /** 937 * Checks if @a pNext is an extent of @a pFirst. 938 * 939 * @returns true if @a pNext is the next extent, false if not 940 * @param pFirst The directory record describing the first or the 941 * previous extent. 942 * @param pNext The directory record alleged to be the next extent. 943 */ 944 DECLINLINE(bool) rtFsIso9660Dir_IsDirRecNextExtent(PCISO9660DIRREC pFirst, PCISO9660DIRREC pNext) 945 { 946 if (RT_LIKELY(pNext->bFileIdLength == pFirst->bFileIdLength)) 947 { 948 if (RT_LIKELY((pNext->fFileFlags | ISO9660_FILE_FLAGS_MULTI_EXTENT) == pFirst->fFileFlags)) 949 { 950 if (RT_LIKELY(memcmp(pNext->achFileId, pFirst->achFileId, pNext->bFileIdLength) == 0)) 951 return true; 952 } 953 } 954 return false; 878 955 } 879 956 … … 1059 1136 { 1060 1137 /* Try match the filename. */ 1061 /** @todo deal with multi-extent filenames, or however that1062 * works... */1063 1138 if (fIsUtf16) 1064 1139 { … … 1086 1161 *poffDirRec = pThis->Core.FirstExtent.offDisk + offEntryInDir; 1087 1162 *ppDirRec = pDirRec; 1088 *pcDirRecs = 1;1089 1163 *pfMode = pDirRec->fFileFlags & ISO9660_FILE_FLAGS_DIRECTORY ? RTFS_TYPE_DIRECTORY : RTFS_TYPE_FILE; 1164 1165 /* 1166 * Deal with the unlikely scenario of multi extent records. 1167 */ 1168 if (!(pDirRec->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT)) 1169 *pcDirRecs = 1; 1170 else 1171 { 1172 offEntryInDir += pDirRec->cbDirRec; 1173 1174 uint32_t cDirRecs = 1; 1175 while (offEntryInDir + RT_UOFFSETOF(ISO9660DIRREC, achFileId) <= cbDir) 1176 { 1177 PCISO9660DIRREC pDirRec2 = (PCISO9660DIRREC)&pThis->pbDir[offEntryInDir]; 1178 if (pDirRec2->cbDirRec != 0) 1179 { 1180 Assert(rtFsIso9660Dir_IsDirRecNextExtent(pDirRec, pDirRec2)); 1181 cDirRecs++; 1182 if (!(pDirRec2->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT)) 1183 break; 1184 offEntryInDir += pDirRec2->cbDirRec; 1185 } 1186 else 1187 offEntryInDir = (offEntryInDir + pThis->Core.pVol->cbSector) & ~(pThis->Core.pVol->cbSector - 1U); 1188 } 1189 1190 *pcDirRecs = cDirRecs; 1191 } 1090 1192 return VINF_SUCCESS; 1091 1193 } … … 1414 1516 RTFSISO9660CORE TmpObj; 1415 1517 RT_ZERO(TmpObj); 1416 rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, cDirRecs, offDirRec, uVersion, pShared->Core.pVol); 1417 rc = rtFsIso9660Core_QueryInfo(&TmpObj, pObjInfo, enmAddAttr); 1518 rc = rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, cDirRecs, offDirRec, uVersion, pShared->Core.pVol); 1519 if (RT_SUCCESS(rc)) 1520 { 1521 rc = rtFsIso9660Core_QueryInfo(&TmpObj, pObjInfo, enmAddAttr); 1522 RTMemFree(TmpObj.paExtents); 1523 } 1418 1524 } 1419 1525 return rc; … … 1561 1667 RTFSISO9660CORE TmpObj; 1562 1668 RT_ZERO(TmpObj); 1563 rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, 1 /*cDirRecs*/, /** @todo multi-extent stuff */1669 rtFsIso9660Core_InitFromDirRec(&TmpObj, pDirRec, 1 /* cDirRecs - see below why 1 */, 1564 1670 pThis->offDir + pShared->Core.FirstExtent.offDisk, uVersion, pShared->Core.pVol); 1565 1671 int rc = rtFsIso9660Core_QueryInfo(&TmpObj, &pDirEntry->Info, enmAddAttr); 1566 1672 1567 1673 /* 1568 * Update the location and return. 1674 * Update the directory location and handle multi extent records. 1675 * 1676 * Multi extent records only affect the file size and the directory location, 1677 * so we deal with it here instead of involving * rtFsIso9660Core_InitFromDirRec 1678 * which would potentially require freeing memory and such. 1569 1679 */ 1570 Log3(("rtFsIso9660Dir_ReadDir: offDir=%#07x: %s (rc=%Rrc)\n", pThis->offDir, pDirEntry->szName, rc)); 1571 pThis->offDir += pDirRec->cbDirRec; 1680 if (!(pDirRec->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT)) 1681 { 1682 Log3(("rtFsIso9660Dir_ReadDir: offDir=%#07x: %s (rc=%Rrc)\n", pThis->offDir, pDirEntry->szName, rc)); 1683 pThis->offDir += pDirRec->cbDirRec; 1684 } 1685 else 1686 { 1687 uint32_t cExtents = 1; 1688 uint32_t offDir = pThis->offDir + pDirRec->cbDirRec; 1689 while (offDir + RT_UOFFSETOF(ISO9660DIRREC, achFileId) <= pShared->cbDir) 1690 { 1691 PCISO9660DIRREC pDirRec2 = (PCISO9660DIRREC)&pShared->pbDir[offDir]; 1692 if (pDirRec2->cbDirRec != 0) 1693 { 1694 pDirEntry->Info.cbObject += ISO9660_GET_ENDIAN(&pDirRec2->cbData); 1695 offDir += pDirRec2->cbDirRec; 1696 cExtents++; 1697 if (!(pDirRec2->fFileFlags & ISO9660_FILE_FLAGS_MULTI_EXTENT)) 1698 break; 1699 } 1700 else 1701 offDir = (offDir + pShared->Core.pVol->cbSector) & ~(pShared->Core.pVol->cbSector - 1U); 1702 } 1703 Log3(("rtFsIso9660Dir_ReadDir: offDir=%#07x, %u extents ending at %#07x: %s (rc=%Rrc)\n", 1704 pThis->offDir, cExtents, offDir, pDirEntry->szName, rc)); 1705 pThis->offDir = offDir; 1706 } 1707 1572 1708 return rc; 1573 1709 } … … 1735 1871 * @param pParentDir The parent directory. This is NULL for the root 1736 1872 * directory. 1737 * @param pDirRec The directory record. 1873 * @param pDirRec The directory record. Will access @a cDirRecs 1874 * records. 1738 1875 * @param cDirRecs Number of directory records if more than one. 1739 1876 * @param offDirRec The byte offset of the directory record. 1740 1877 * @param ppShared Where to return the shared directory structure. 1741 1878 */ 1742 static int 1743 1879 static int rtFsIso9660DirShrd_New(PRTFSISO9660VOL pThis, PRTFSISO9660DIRSHRD pParentDir, PCISO9660DIRREC pDirRec, 1880 uint32_t cDirRecs, uint64_t offDirRec, PRTFSISO9660DIRSHRD *ppShared) 1744 1881 { 1745 1882 /* … … 1750 1887 if (pShared) 1751 1888 { 1752 rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, 0 /*uVersion*/, pThis); 1753 RTListInit(&pShared->OpenChildren); 1754 pShared->cbDir = ISO9660_GET_ENDIAN(&pDirRec->cbData); 1755 pShared->pbDir = (uint8_t *)RTMemAllocZ(pShared->cbDir + 256); 1756 if (pShared->pbDir) 1757 { 1758 rc = RTVfsFileReadAt(pThis->hVfsBacking, pShared->Core.FirstExtent.offDisk, pShared->pbDir, pShared->cbDir, NULL); 1759 if (RT_SUCCESS(rc)) 1889 rc = rtFsIso9660Core_InitFromDirRec(&pShared->Core, pDirRec, cDirRecs, offDirRec, 0 /*uVersion*/, pThis); 1890 if (RT_SUCCESS(rc)) 1891 { 1892 RTListInit(&pShared->OpenChildren); 1893 pShared->cbDir = ISO9660_GET_ENDIAN(&pDirRec->cbData); 1894 pShared->pbDir = (uint8_t *)RTMemAllocZ(pShared->cbDir + 256); 1895 if (pShared->pbDir) 1760 1896 { 1897 rc = RTVfsFileReadAt(pThis->hVfsBacking, pShared->Core.FirstExtent.offDisk, pShared->pbDir, pShared->cbDir, NULL); 1898 if (RT_SUCCESS(rc)) 1899 { 1761 1900 #ifdef LOG_ENABLED 1762 rtFsIso9660DirShrd_LogContent(pShared);1901 rtFsIso9660DirShrd_LogContent(pShared); 1763 1902 #endif 1764 1903 1765 /* 1766 * Link into parent directory so we can use it to update 1767 * our directory entry. 1768 */ 1769 if (pParentDir) 1770 rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core); 1771 *ppShared = pShared; 1772 return VINF_SUCCESS; 1904 /* 1905 * Link into parent directory so we can use it to update 1906 * our directory entry. 1907 */ 1908 if (pParentDir) 1909 rtFsIso9660DirShrd_AddOpenChild(pParentDir, &pShared->Core); 1910 *ppShared = pShared; 1911 return VINF_SUCCESS; 1912 } 1773 1913 } 1774 1914 } 1915 RTMemFree(pShared); 1775 1916 } 1776 1917 *ppShared = NULL;
Note:
See TracChangeset
for help on using the changeset viewer.