Changeset 67838 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Jul 6, 2017 4:18:43 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/isomaker.cpp
r67801 r67838 77 77 /** UTF-8 name buffer. */ 78 78 #define RTFSISOMAKER_MAX_NAME_BUF 768 79 80 /** Max symbolic link target length. */ 81 #define RTFSISOMAKER_MAX_SYMLINK_TARGET_LEN 260 79 82 80 83 /** TRANS.TBL left padding length. … … 205 208 /** Set if pszTransNm is allocated separately. Normally same as pszSpecNm. */ 206 209 bool fTransNmAlloced : 1; 210 /** Set if we need to emit an ER entry (root only). */ 211 bool fRockNeedER : 1; 212 /** Set if we need to emit a RR entry in the directory record. */ 213 bool fRockNeedRRInDirRec : 1; 214 /** Set if we need to emit a RR entry in the spill file. */ 215 bool fRockNeedRRInSpill : 1; 207 216 208 217 /** The mode mask. … … 218 227 * This is for Rock Ridge. */ 219 228 RTDEV Device; 220 /** The inode/serial number.221 * This is for Rock Ridge. */222 uint64_t INode;223 229 /** The number of hardlinks to report in the file stats. 224 230 * This is for Rock Ridge. */ … … 235 241 * sector zero padding. */ 236 242 uint16_t cbDirRecTotal; 243 244 /** Rock ridge flags (ISO9660RRIP_RR_F_XXX). */ 245 uint8_t fRockEntries; 246 /** Number of rock ridge data bytes in the directory record. */ 247 uint8_t cbRockInDirRec; 248 /** Rock ridge spill file data offset, UINT32_MAX if placed in dir record. */ 249 uint32_t offRockSpill; 250 /** Size of rock data in spill file. */ 251 uint16_t cbRockSpill; 237 252 238 253 /** The number of bytes the name requires in the directory record. */ … … 354 369 RTFSISOMAKERSRCTYPE_COMMON, 355 370 RTFSISOMAKERSRCTYPE_TRANS_TBL, 371 RTFSISOMAKERSRCTYPE_RR_SPILL, 356 372 RTFSISOMAKERSRCTYPE_END 357 373 } RTFSISOMAKERSRCTYPE; … … 390 406 /** The directory the translation table belongs to. */ 391 407 PRTFSISOMAKERNAME pTransTblDir; 408 /** The namespace for a rock ridge spill file.. */ 409 PRTFSISOMAKERNAMESPACE pRockSpillNamespace; 392 410 } u; 393 411 … … 423 441 /** The common bit. */ 424 442 RTFSISOMAKEROBJ Core; 443 /** The size of the rock ridge 'SL' records for this link. */ 444 uint16_t cbSlRockRidge; 425 445 /** The symbolic link target length. */ 426 size_tcchTarget;446 uint16_t cchTarget; 427 447 /** The symbolic link target. */ 428 448 char szTarget[RT_FLEXIBLE_ARRAY]; … … 430 450 /** Pointer to an ISO maker directory object. */ 431 451 typedef RTFSISOMAKERSYMLINK *PRTFSISOMAKERSYMLINK; 452 /** Pointer to a const ISO maker directory object. */ 453 typedef const RTFSISOMAKERSYMLINK *PCRTFSISOMAKERSYMLINK; 432 454 433 455 … … 594 616 /** Current directory hint for the joliet namespace. */ 595 617 PRTFSISOMAKERNAMEDIR pDirHintJoliet; 618 /** Joliet directory child index hint. */ 619 uint32_t iChildPrimaryIso; 620 /** Joliet directory child index hint. */ 621 uint32_t iChildJoliet; 596 622 } RTFSISOMAKEROUTPUTFILE; 597 623 /** Pointer to the instance data of an ISO maker output file. */ … … 670 696 static int rtFsIsoMakerObjRemoveWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj); 671 697 698 static ssize_t rtFsIsoMakerOutFile_RockRidgeGenSL(const char *pszTarget, uint8_t *pbBuf, size_t cbBuf); 672 699 static DECLCALLBACK(int) rtFsIsoMakerOutFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual); 673 700 … … 686 713 */ 687 714 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_ISO_9660]].fNamespace == RTFSISOMAKER_NAMESPACE_ISO_9660, 688 VERR_I NTERNAL_ERROR_5);715 VERR_ISOMK_IPE_TABLE); 689 716 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_JOLIET]].fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET, 690 VERR_I NTERNAL_ERROR_5);717 VERR_ISOMK_IPE_TABLE); 691 718 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_UDF]].fNamespace == RTFSISOMAKER_NAMESPACE_UDF, 692 VERR_I NTERNAL_ERROR_5);719 VERR_ISOMK_IPE_TABLE); 693 720 AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_HFS]].fNamespace == RTFSISOMAKER_NAMESPACE_HFS, 694 VERR_I NTERNAL_ERROR_5);721 VERR_ISOMK_IPE_TABLE); 695 722 696 723 if (g_szAppIdPrimaryIso[0] == '\0') … … 870 897 871 898 case RTFSISOMAKERSRCTYPE_COMMON: 899 case RTFSISOMAKERSRCTYPE_RR_SPILL: 872 900 break; 873 901 … … 1544 1572 while (RTPATH_IS_SLASH(*pszPath)) 1545 1573 pszPath++; 1546 AssertReturn(*pszPath, VERR_I NTERNAL_ERROR_4);1574 AssertReturn(*pszPath, VERR_ISOMK_IPE_EMPTY_PATH); 1547 1575 1548 1576 PRTFSISOMAKERNAME pCur = pNamespace->pRoot; … … 1667 1695 char *pszDst, size_t cbDst, size_t *pcchDst, size_t *pcbInDirRec) 1668 1696 { 1669 AssertReturn(cbDst > ISO9660_MAX_NAME_LEN + 2, VERR_I NTERNAL_ERROR_3);1697 AssertReturn(cbDst > ISO9660_MAX_NAME_LEN + 2, VERR_ISOMK_IPE_BUFFER_SIZE); 1670 1698 1671 1699 /* Skip leading dots. */ … … 1842 1870 1843 1871 default: 1844 AssertFailedReturn(VERR_I NTERNAL_ERROR_2);1872 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE); 1845 1873 } 1846 1874 } … … 1857 1885 *pcchDst = 0; 1858 1886 *pcbInDirRec = pNamespace->fNamespace & (RTFSISOMAKER_NAMESPACE_ISO_9660 | RTFSISOMAKER_NAMESPACE_JOLIET) ? 1 : 0; 1859 AssertReturn(!pParent, VERR_I NTERNAL_ERROR_3);1887 AssertReturn(!pParent, VERR_ISOMK_IPE_NAMESPACE_3); 1860 1888 return VINF_SUCCESS; 1861 1889 } … … 1970 1998 if (pParent) 1971 1999 { 1972 AssertReturn(pParent->pDir, VERR_I NTERNAL_ERROR_5);2000 AssertReturn(pParent->pDir, VERR_ISOMK_IPE_NAMESPACE_1); 1973 2001 uint32_t cChildren = pParent->pDir->cChildren; 1974 2002 if (cChildren & 31) … … 1983 2011 } 1984 2012 else 1985 AssertReturn(pNamespace->pRoot == NULL, VERR_I NTERNAL_ERROR_5);2013 AssertReturn(pNamespace->pRoot == NULL, VERR_ISOMK_IPE_NAMESPACE_2); 1986 2014 1987 2015 /* … … 2023 2051 pName->fRockRidgeNmAlloced = false; 2024 2052 pName->fTransNmAlloced = false; 2053 pName->fRockNeedER = false; 2054 pName->fRockNeedRRInDirRec = false; 2055 pName->fRockNeedRRInSpill = false; 2025 2056 2026 2057 pName->fMode = pObj->fMode; … … 2028 2059 pName->gid = pObj->gid; 2029 2060 pName->Device = 0; 2030 pName->INode = pObj->idxObj;2031 2061 pName->cHardlinks = 1; 2032 2062 pName->offDirRec = UINT32_MAX; … … 2034 2064 pName->cDirRecs = 1; 2035 2065 pName->cbDirRecTotal = 0; 2066 pName->fRockEntries = 0; 2067 pName->cbRockInDirRec = 0; 2068 pName->offRockSpill = UINT32_MAX; 2069 pName->cbRockSpill = 0; 2036 2070 2037 2071 memcpy(pName->szName, szName, cchName); … … 2122 2156 2123 2157 int rc; 2124 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_I NTERNAL_ERROR_4);2158 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_ISOMK_IPE_ROOT_SLASH); 2125 2159 2126 2160 /* … … 2129 2163 while (RTPATH_IS_SLASH(*pszPath)) 2130 2164 pszPath++; 2131 AssertReturn(*pszPath, VERR_I NTERNAL_ERROR_4); /* We should not be called on a root path. */2165 AssertReturn(*pszPath, VERR_ISOMK_IPE_EMPTY_PATH); /* We should not be called on a root path. */ 2132 2166 2133 2167 PRTFSISOMAKERNAME pParent = pNamespace->pRoot; … … 2145 2179 AssertRCReturn(rc, rc); 2146 2180 pParent = pNamespace->pRoot; 2147 AssertReturn(pParent, VERR_I NTERNAL_ERROR_4);2181 AssertReturn(pParent, VERR_ISOMK_IPE_NAMESPACE_4); 2148 2182 } 2149 2183 … … 2160 2194 while ((ch = pszPath[cchComponent]) != '\0' && !RTPATH_IS_SLASH(ch)) 2161 2195 cchComponent++; 2162 AssertReturn(cchComponent > 0, VERR_I NTERNAL_ERROR_4);2196 AssertReturn(cchComponent > 0, VERR_ISOMK_IPE_EMPTY_COMPONENT); 2163 2197 2164 2198 size_t offNext = cchComponent; … … 2220 2254 if (RT_FAILURE(rc)) 2221 2255 return rc; 2222 AssertReturn(pChild != NULL, VERR_I NTERNAL_ERROR_4);2256 AssertReturn(pChild != NULL, VERR_ISOMK_IPE_NAMESPACE_5); 2223 2257 } 2224 2258 } … … 2231 2265 if (RT_FAILURE(rc)) 2232 2266 return rc; 2233 AssertReturn(pChild != NULL, VERR_I NTERNAL_ERROR_4);2267 AssertReturn(pChild != NULL, VERR_ISOMK_IPE_NAMESPACE_5); 2234 2268 } 2235 2269 pParent = pChild; … … 2258 2292 { 2259 2293 AssertReturn(*rtFsIsoMakerObjGetNameForNamespace(pObj, pNamespace) == NULL, VERR_WRONG_ORDER); 2260 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_I NTERNAL_ERROR_5);2294 AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_ISOMK_IPE_ROOT_SLASH); 2261 2295 2262 2296 /* … … 2363 2397 /* Not found. This can't happen. */ 2364 2398 AssertFailed(); 2365 return VERR_I NTERNAL_ERROR_2;2399 return VERR_ISOMK_IPE_NAMESPACE_6; 2366 2400 } 2367 2401 … … 2526 2560 PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj); 2527 2561 AssertReturn(pObj, VERR_OUT_OF_RANGE); 2562 AssertReturn( pObj->enmType != RTFSISOMAKEROBJTYPE_FILE 2563 || ((PRTFSISOMAKERFILE)pObj)->enmSrcType != RTFSISOMAKERSRCTYPE_RR_SPILL, VERR_ACCESS_DENIED); 2528 2564 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 2529 2565 … … 2807 2843 { 2808 2844 PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pObj; 2809 if (pFile->enmSrcType != RTFSISOMAKERSRCTYPE_TRANS_TBL) 2845 if ( pFile->enmSrcType != RTFSISOMAKERSRCTYPE_TRANS_TBL 2846 && pFile->enmSrcType != RTFSISOMAKERSRCTYPE_RR_SPILL) 2810 2847 { 2811 2848 *pcbData = ((PRTFSISOMAKERFILE)pObj)->cbData; … … 3333 3370 size_t cchTarget = strlen(pszTarget); 3334 3371 AssertPtrReturn(cchTarget > 0, VERR_INVALID_NAME); 3335 AssertPtrReturn(cchTarget < _1K, VERR_FILENAME_TOO_LONG);3372 AssertPtrReturn(cchTarget < RTFSISOMAKER_MAX_SYMLINK_TARGET_LEN, VERR_FILENAME_TOO_LONG); 3336 3373 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 3337 3374 … … 3346 3383 3347 3384 /* 3385 * Calculate the size of the SL entries. 3386 */ 3387 uint8_t abTmp[_2K + RTFSISOMAKER_MAX_SYMLINK_TARGET_LEN * 3]; 3388 ssize_t cbSlRockRidge = rtFsIsoMakerOutFile_RockRidgeGenSL(pszTarget, abTmp, sizeof(abTmp)); 3389 AssertReturn(cbSlRockRidge > 0, (int)cbSlRockRidge); 3390 3391 /* 3348 3392 * Do the adding. 3349 3393 */ … … 3353 3397 if (RT_SUCCESS(rc)) 3354 3398 { 3399 pSymlink->cchTarget = (uint16_t)cchTarget; 3400 pSymlink->cbSlRockRidge = (uint16_t)cbSlRockRidge; 3355 3401 memcpy(pSymlink->szTarget, pszTarget, cchTarget); 3356 3402 pSymlink->szTarget[cchTarget] = '\0'; 3357 pSymlink->cchTarget = cchTarget; 3403 3358 3404 return VINF_SUCCESS; 3359 3405 } … … 3557 3603 } 3558 3604 else 3559 rc = VERR_I NTERNAL_ERROR_2;3605 rc = VERR_ISOMK_IPE_BOOT_CAT_FILE; 3560 3606 } 3561 3607 return rc; … … 4102 4148 * @param pName The directory entry to finalize. 4103 4149 * @param offInDir The offset in the directory of this record. 4104 * @param uRo otRockRidge This is the rock ridge level when4105 * root, otherwise it's zero.4150 * @param uRockRidgeLevel This is the rock ridge level. 4151 * @param fIsRoot Set if this is the root. 4106 4152 */ 4107 4153 static int rtFsIsoMakerFinalizeIsoDirectoryEntry(PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs, PRTFSISOMAKERNAME pName, 4108 uint32_t offInDir, uint8_t uRo otRockRidge)4154 uint32_t offInDir, uint8_t uRockRidgeLevel, bool fIsRoot) 4109 4155 { 4110 4156 /* Set directory and translation table offsets. (These are for … … 4126 4172 4127 4173 /* 4128 * Calculate additional rock ridge stuff, if it doesn't all fit write it 4129 * to the spill file. 4130 */ 4131 if (pFinalizedDirs->pRRSpillFile) 4132 { 4133 /** @todo rock ridge */ 4134 RT_NOREF(uRootRockRidge); 4174 * Calculate the size of the rock ridge bits we need. 4175 */ 4176 if (uRockRidgeLevel > 0) 4177 { 4178 uint16_t cbRock = 0; 4179 uint8_t fFlags = 0; 4180 4181 /* Level two starts with a 'RR' entry. */ 4182 if (uRockRidgeLevel >= 2) 4183 cbRock += sizeof(ISO9660RRIPRR); 4184 4185 /* We always do 'PX' and 'TF' w/ 4 timestamps. */ 4186 cbRock = sizeof(ISO9660RRIPPX) 4187 + RT_OFFSETOF(ISO9660RRIPTF, abPayload) + 4 * sizeof(ISO9660RECTIMESTAMP); 4188 fFlags |= ISO9660RRIP_RR_F_PX | ISO9660RRIP_RR_F_TF; 4189 4190 /* Devices needs 'PN'. */ 4191 if ( RTFS_IS_DEV_BLOCK(pName->pObj->fMode) 4192 || RTFS_IS_DEV_BLOCK(pName->pObj->fMode)) 4193 { 4194 cbRock += sizeof(ISO9660RRIPPN); 4195 fFlags |= ISO9660RRIP_RR_F_PN; 4196 } 4197 4198 /* Usually we need a 'NM' entry too. */ 4199 if ( pName->pszRockRidgeNm != pName->szName 4200 && pName->cchRockRidgeNm > 0 4201 && ( pName->cbNameInDirRec != 1 4202 || (uint8_t)pName->szName[0] > (uint8_t)0x01) ) 4203 { 4204 cbRock += (pName->cchRockRidgeNm + ISO9660RRIPNM_MAX_NAME_LEN - 1) / ISO9660RRIPNM_MAX_NAME_LEN; 4205 fFlags |= ISO9660RRIP_RR_F_NM; 4206 } 4207 4208 /* Symbolic links needs a 'SL' entry. */ 4209 if (pName->pObj->enmType == RTFSISOMAKEROBJTYPE_SYMLINK) 4210 { 4211 PRTFSISOMAKERSYMLINK pSymlink = (PRTFSISOMAKERSYMLINK)pName->pObj; 4212 cbRock += pSymlink->cbSlRockRidge; 4213 fFlags |= ISO9660RRIP_RR_F_SL; 4214 } 4215 4216 /* 4217 * Decide where stuff goes. The '.' record of the root dir is special. 4218 */ 4219 pName->fRockEntries = fFlags; 4220 if (!fIsRoot) 4221 { 4222 if (pName->cbDirRec + cbRock < UINT8_MAX) 4223 { 4224 pName->cbRockInDirRec = cbRock + (cbRock & 1); 4225 pName->cbRockSpill = 0; 4226 pName->fRockNeedRRInDirRec = uRockRidgeLevel >= 2; 4227 pName->fRockNeedRRInSpill = false; 4228 } 4229 else if (pName->cbDirRec + sizeof(ISO9660SUSPCE) < UINT8_MAX) 4230 { 4231 /* Try fit the 'RR' entry in the directory record, but don't bother with anything else. */ 4232 if (uRockRidgeLevel >= 2 && pName->cbDirRec + sizeof(ISO9660SUSPCE) + sizeof(ISO9660RRIPRR) < UINT8_MAX) 4233 { 4234 pName->cbRockInDirRec = RT_ALIGN_T(sizeof(ISO9660SUSPCE) + sizeof(ISO9660RRIPRR), 2, uint16_t); 4235 cbRock -= sizeof(ISO9660RRIPRR); 4236 pName->cbRockSpill = cbRock; 4237 pName->fRockNeedRRInDirRec = true; 4238 pName->fRockNeedRRInSpill = false; 4239 } 4240 else 4241 { 4242 pName->cbRockInDirRec = RT_ALIGN_T(sizeof(ISO9660SUSPCE), 2, uint16_t); 4243 pName->cbRockSpill = cbRock; 4244 pName->fRockNeedRRInDirRec = false; 4245 pName->fRockNeedRRInSpill = uRockRidgeLevel >= 2; 4246 } 4247 if (ISO9660_SECTOR_SIZE - (pFinalizedDirs->pRRSpillFile->cbData & ISO9660_SECTOR_OFFSET_MASK) < cbRock) 4248 pFinalizedDirs->pRRSpillFile->cbData = (pFinalizedDirs->pRRSpillFile->cbData | ISO9660_SECTOR_OFFSET_MASK) + 1; 4249 pName->offRockSpill = pFinalizedDirs->pRRSpillFile->cbData; 4250 pFinalizedDirs->pRRSpillFile->cbData += RT_ALIGN_T(cbRock, 4, uint16_t); 4251 } 4252 else 4253 { 4254 LogRel(("RTFsIsoMaker: no space for 'CE' entry: cbDirRec=%#x bytes, name=%s (%#x bytes)\n", 4255 pName->cbDirRec, pName->szName, pName->cbNameInDirRec)); 4256 return VERR_ISOMK_RR_NO_SPACE_FOR_CE; 4257 } 4258 } 4259 else 4260 { 4261 /* The root starts with a 'SP' record to indicate that SUSP is being used, 4262 this is always in the directory record. If we add a 'ER' record (big) too, 4263 we put all but 'SP' and 'ER' in the spill file too keep things simple. */ 4264 if (uRockRidgeLevel < 2) 4265 { 4266 Assert(!(fFlags & (ISO9660RRIP_RR_F_NM | ISO9660RRIP_RR_F_SL | ISO9660RRIP_RR_F_CL | ISO9660RRIP_RR_F_PL | ISO9660RRIP_RR_F_RE))); 4267 cbRock += sizeof(ISO9660SUSPSP); 4268 Assert(pName->cbDirRec + cbRock < UINT8_MAX); 4269 pName->cbRockInDirRec = cbRock + (cbRock & 1); 4270 pName->cbRockSpill = 0; 4271 pName->fRockNeedER = false; 4272 pName->fRockNeedRRInDirRec = false; 4273 pName->fRockNeedRRInSpill = false; 4274 } 4275 else 4276 { 4277 pName->cbRockInDirRec = RT_ALIGN_T(sizeof(ISO9660SUSPSP) + sizeof(ISO9660SUSPCE), 2, uint16_t); 4278 pName->fRockNeedER = true; 4279 pName->fRockNeedRRInSpill = true; 4280 pName->fRockNeedRRInDirRec = false; 4281 cbRock += ISO9660_RRIP_ER_LEN; 4282 pName->cbRockSpill = cbRock; 4283 if ( ISO9660_SECTOR_SIZE - (pFinalizedDirs->pRRSpillFile->cbData & ISO9660_SECTOR_OFFSET_MASK) < cbRock) 4284 pFinalizedDirs->pRRSpillFile->cbData = (pFinalizedDirs->pRRSpillFile->cbData | ISO9660_SECTOR_OFFSET_MASK) + 1; 4285 pName->offRockSpill = pFinalizedDirs->pRRSpillFile->cbData; 4286 pFinalizedDirs->pRRSpillFile->cbData += RT_ALIGN_T(cbRock, 4, uint16_t); 4287 } 4288 } 4289 pName->cbDirRec += pName->cbRockInDirRec; 4290 Assert(pName->cbDirRec < UINT8_MAX); 4135 4291 } 4136 4292 … … 4154 4310 PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs, uint64_t *poffData) 4155 4311 { 4312 int rc; 4313 4156 4314 /* The directory data comes first, so take down it's offset. */ 4157 4315 pFinalizedDirs->offDirs = *poffData; … … 4164 4322 if (pFinalizedDirs->pRRSpillFile) 4165 4323 { 4324 pFinalizedDirs->pRRSpillFile->Core.cNotOrphan = 0; 4166 4325 rtFsIsoMakerObjRemoveWorker(pThis, &pFinalizedDirs->pRRSpillFile->Core); 4167 4326 pFinalizedDirs->pRRSpillFile = NULL; … … 4169 4328 if (pNamespace->uRockRidgeLevel > 0) 4170 4329 { 4171 /** @todo create rock ridge spill file to indicate rock ridge */ 4172 } 4173 4174 int rc; 4330 rc = rtFsIsoMakerAddUnnamedFileWorker(pThis, NULL, 0, &pFinalizedDirs->pRRSpillFile); 4331 AssertRCReturn(rc, rc); 4332 pFinalizedDirs->pRRSpillFile->enmSrcType = RTFSISOMAKERSRCTYPE_RR_SPILL; 4333 pFinalizedDirs->pRRSpillFile->u.pRockSpillNamespace = pNamespace; 4334 pFinalizedDirs->pRRSpillFile->Core.cNotOrphan = 1; 4335 } 4336 4175 4337 uint16_t idPathTable = 1; 4176 4338 uint32_t cbPathTable = 0; … … 4180 4342 * Precalc the directory record size for the root directory. 4181 4343 */ 4182 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, pNamespace->uRockRidgeLevel); 4344 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, 4345 pNamespace->uRockRidgeLevel, true /*fIsRoot*/); 4183 4346 AssertRCReturn(rc, rc); 4184 4347 … … 4203 4366 4204 4367 /* Finalize the directory entries. */ 4368 uint32_t cSubDirs = 0; 4205 4369 uint32_t cbTransTbl = 0; 4206 4370 uint32_t cLeft = pCurDir->cChildren; … … 4209 4373 { 4210 4374 PRTFSISOMAKERNAME pChild = *ppChild++; 4211 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, 0 /*uRootRockRidge*/); 4375 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, 4376 pNamespace->uRockRidgeLevel, false /*fIsRoot*/); 4212 4377 AssertRCReturn(rc, rc); 4213 4378 … … 4234 4399 + pChild->cchTransNm 4235 4400 + 1 /* newline */; 4401 4402 if (RTFS_IS_DIRECTORY(pChild->fMode)) 4403 cSubDirs++; 4236 4404 } 4237 4405 … … 4252 4420 pCurDir->idPathTable = idPathTable++; 4253 4421 cbPathTable += RTFSISOMAKER_CALC_PATHREC_SIZE(pCurName->cbNameInDirRec); 4422 4423 /* Set the hardlink count. */ 4424 pCurName->cHardlinks = cSubDirs + 2; 4254 4425 4255 4426 Log4(("rtFsIsoMakerFinalizeDirectoriesInIsoNamespace: idxObj=#%#x cbDir=%#08x cChildren=%#05x %s\n", … … 4380 4551 break; 4381 4552 default: 4382 AssertMsgFailedReturn(("enmSrcType=%d\n", pCurFile->enmSrcType), VERR_I NTERNAL_ERROR_3);4553 AssertMsgFailedReturn(("enmSrcType=%d\n", pCurFile->enmSrcType), VERR_IPE_NOT_REACHED_DEFAULT_CASE); 4383 4554 } 4384 4555 … … 4601 4772 /** @todo UDF descriptors. */ 4602 4773 } 4603 AssertReturn(offVolDescs == pThis->cVolumeDescriptors * RTFSISOMAKER_SECTOR_SIZE, VERR_I NTERNAL_ERROR_2);4774 AssertReturn(offVolDescs == pThis->cVolumeDescriptors * RTFSISOMAKER_SECTOR_SIZE, VERR_ISOMK_IPE_DESC_COUNT); 4604 4775 4605 4776 /* … … 4737 4908 static int rtFsIsoMakerFinalizeVolumeDescriptors(PRTFSISOMAKERINT pThis) 4738 4909 { 4739 AssertReturn(pThis->pbVolDescs && pThis->pPrimaryVolDesc && pThis->pTerminatorVolDesc, VERR_I NTERNAL_ERROR_3);4910 AssertReturn(pThis->pbVolDescs && pThis->pPrimaryVolDesc && pThis->pTerminatorVolDesc, VERR_ISOMK_IPE_FINALIZE_1); 4740 4911 4741 4912 /* … … 4950 5121 4951 5122 /** 5123 * Generates the 'SL' records for a symbolic link. 5124 * 5125 * This is used both when generating directories records, spill file data and 5126 * when creating the symbolic link. 5127 * 5128 * @returns Number of bytes produced. Negative IPRT status if buffer overflow. 5129 * @param pszTarget The symbolic link target to encode. 5130 * @param pbBuf The output buffer. 5131 * @param cbBuf The size of the output buffer. 5132 */ 5133 static ssize_t rtFsIsoMakerOutFile_RockRidgeGenSL(const char *pszTarget, uint8_t *pbBuf, size_t cbBuf) 5134 { 5135 Assert(*pszTarget != '\0'); 5136 5137 PISO9660RRIPSL pEntry = (PISO9660RRIPSL)pbBuf; 5138 pEntry->Hdr.bSig1 = ISO9660RRIPSL_SIG1; 5139 pEntry->Hdr.bSig2 = ISO9660RRIPSL_SIG2; 5140 pEntry->Hdr.cbEntry = 0; /* set later. */ 5141 pEntry->Hdr.bVersion = ISO9660RRIPSL_VER; 5142 pEntry->fFlags = 0; 5143 size_t offEntry = 0; 5144 size_t off = pEntry->Hdr.cbEntry; 5145 5146 /* Does it start with a root slash? */ 5147 if (RTPATH_IS_SLASH(*pszTarget)) 5148 { 5149 pbBuf[off++] = ISO9660RRIP_SL_C_ROOT; 5150 pbBuf[off++] = 0; 5151 pszTarget++; 5152 } 5153 5154 for (;;) 5155 { 5156 /* Find the end of the component. */ 5157 size_t cchComponent = 0; 5158 char ch; 5159 while ((ch = pszTarget[cchComponent]) != '\0' && !RTPATH_IS_SLASH(ch)) 5160 cchComponent++; 5161 5162 /* Check for dots and figure out how much space we need. */ 5163 uint8_t fFlags; 5164 size_t cbNeeded; 5165 if (cchComponent == 1 && *pszTarget == '.') 5166 { 5167 fFlags = ISO9660RRIP_SL_C_CURRENT; 5168 cbNeeded = 2; 5169 } 5170 else if (cchComponent == 2 && pszTarget[0] == '.' && pszTarget[1] == '.') 5171 { 5172 fFlags = ISO9660RRIP_SL_C_PARENT; 5173 cbNeeded = 0; 5174 } 5175 else 5176 { 5177 fFlags = 0; 5178 cbNeeded = 2 + cchComponent; 5179 } 5180 5181 /* Split the SL record if we're out of space. */ 5182 if ( off - offEntry + cbNeeded < UINT8_MAX 5183 && off + cbNeeded <= cbBuf) 5184 { /* likely */ } 5185 else if (cbNeeded + RT_OFFSETOF(ISO9660RRIPSL, abComponents) < UINT8_MAX) 5186 { 5187 AssertReturn(off + cbNeeded + RT_OFFSETOF(ISO9660RRIPSL, abComponents) <= cbBuf, VERR_BUFFER_OVERFLOW); 5188 Assert(off - offEntry < UINT8_MAX); 5189 pEntry->Hdr.cbEntry = (uint8_t)(off - offEntry); 5190 pEntry->fFlags |= ISO9660RRIP_SL_F_CONTINUE; 5191 5192 offEntry = off; 5193 pEntry = (PISO9660RRIPSL)&pbBuf[off]; 5194 pEntry->Hdr.bSig1 = ISO9660RRIPSL_SIG1; 5195 pEntry->Hdr.bSig2 = ISO9660RRIPSL_SIG2; 5196 pEntry->Hdr.cbEntry = 0; /* set later. */ 5197 pEntry->Hdr.bVersion = ISO9660RRIPSL_VER; 5198 pEntry->fFlags = 0; 5199 } 5200 else 5201 { 5202 /* Special case: component doesn't fit in a single SL entry. */ 5203 do 5204 { 5205 if (off - offEntry + 3 < UINT8_MAX) 5206 { 5207 size_t cchLeft = UINT8_MAX - 1 - (off - offEntry) - 2; 5208 size_t cchToCopy = RT_MIN(cchLeft, cchComponent); 5209 AssertReturn(off + 2 + cchToCopy <= cbBuf, VERR_BUFFER_OVERFLOW); 5210 pbBuf[off++] = cchToCopy < cchComponent ? ISO9660RRIP_SL_C_CONTINUE : 0; 5211 pbBuf[off++] = (uint8_t)cchToCopy; 5212 memcpy(&pbBuf[off], pszTarget, cchToCopy); 5213 off += pbBuf[off++]; 5214 pszTarget += cchToCopy; 5215 cchComponent -= cchToCopy; 5216 if (!cchComponent) 5217 break; 5218 } 5219 5220 Assert(off - offEntry < UINT8_MAX); 5221 pEntry->Hdr.cbEntry = (uint8_t)(off - offEntry); 5222 pEntry->fFlags |= ISO9660RRIP_SL_F_CONTINUE; 5223 5224 AssertReturn(off + 2 + cchComponent + RT_OFFSETOF(ISO9660RRIPSL, abComponents) <= cbBuf, VERR_BUFFER_OVERFLOW); 5225 offEntry = off; 5226 pEntry = (PISO9660RRIPSL)&pbBuf[off]; 5227 pEntry->Hdr.bSig1 = ISO9660RRIPSL_SIG1; 5228 pEntry->Hdr.bSig2 = ISO9660RRIPSL_SIG2; 5229 pEntry->Hdr.cbEntry = 0; /* set later. */ 5230 pEntry->Hdr.bVersion = ISO9660RRIPSL_VER; 5231 pEntry->fFlags = 0; 5232 5233 5234 } while (cchComponent > 0); 5235 if (ch == '\0') 5236 break; 5237 continue; 5238 } 5239 5240 /* Produce the record. */ 5241 pbBuf[off++] = fFlags; 5242 pbBuf[off++] = (uint8_t)(cbNeeded - 2); 5243 if (cchComponent > 0) 5244 { 5245 memcpy(&pbBuf[off], pszTarget, cbNeeded - 2); 5246 off += cbNeeded - 2; 5247 } 5248 5249 if (ch == '\0') 5250 break; 5251 pszTarget += cchComponent; 5252 } 5253 5254 Assert(off - offEntry < UINT8_MAX); 5255 pEntry->Hdr.cbEntry = (uint8_t)(off - offEntry); 5256 return off; 5257 } 5258 5259 5260 /** 5261 * Generates rock ridge data. 5262 * 5263 * This is used both for the directory record and for the spill file ('CE'). 5264 * 5265 * @param pName The name to generate rock ridge info for. 5266 * @param pbSys The output buffer. 5267 * @param cbSys The size of the output buffer. 5268 * @param fInSpill Indicates whether we're in a spill file (true) or 5269 * directory record (false). 5270 */ 5271 static void rtFsIosMakerOutFile_GenerateRockRidge(PRTFSISOMAKERNAME pName, uint8_t *pbSys, size_t cbSys, bool fInSpill) 5272 { 5273 /* 5274 * Deal with records specific to the root directory '.' entry. 5275 */ 5276 if (pName->pParent != NULL) 5277 { /* likely */ } 5278 else 5279 { 5280 if (!fInSpill) 5281 { 5282 PISO9660SUSPSP pSP = (PISO9660SUSPSP)pbSys; 5283 Assert(cbSys >= sizeof(*pSP)); 5284 pSP->Hdr.bSig1 = ISO9660SUSPSP_SIG1; 5285 pSP->Hdr.bSig2 = ISO9660SUSPSP_SIG2; 5286 pSP->Hdr.cbEntry = ISO9660SUSPSP_LEN; 5287 pSP->Hdr.bVersion = ISO9660SUSPSP_VER; 5288 pSP->bCheck1 = ISO9660SUSPSP_CHECK1; 5289 pSP->bCheck2 = ISO9660SUSPSP_CHECK2; 5290 pSP->cbSkip = 0; 5291 pbSys += sizeof(*pSP); 5292 cbSys -= sizeof(*pSP); 5293 } 5294 if (pName->fRockNeedER) 5295 { 5296 PISO9660SUSPER pER = (PISO9660SUSPER)pbSys; 5297 Assert(cbSys >= ISO9660_RRIP_ER_LEN); 5298 AssertCompile(ISO9660_RRIP_ER_LEN < UINT8_MAX); 5299 pER->Hdr.bSig1 = ISO9660SUSPER_SIG1; 5300 pER->Hdr.bSig2 = ISO9660SUSPER_SIG2; 5301 pER->Hdr.cbEntry = ISO9660_RRIP_ER_LEN; 5302 pER->Hdr.bVersion = ISO9660SUSPER_VER; 5303 pER->cchIdentifier = sizeof(ISO9660_RRIP_ID) - 1; 5304 pER->cchDescription = sizeof(ISO9660_RRIP_DESC) - 1; 5305 pER->cchSource = sizeof(ISO9660_RRIP_SRC) - 1; 5306 memcpy(&pER->achPayload[0], RT_STR_TUPLE(ISO9660_RRIP_ID)); 5307 memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID)], RT_STR_TUPLE(ISO9660_RRIP_DESC)); 5308 memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID) + sizeof(ISO9660_RRIP_DESC)], RT_STR_TUPLE(ISO9660_RRIP_SRC)); 5309 pbSys += ISO9660_RRIP_ER_LEN; 5310 cbSys -= ISO9660_RRIP_ER_LEN; 5311 } 5312 } 5313 5314 /* 5315 * Deal with common stuff. 5316 */ 5317 if (!fInSpill ? pName->fRockNeedRRInDirRec : pName->fRockNeedRRInSpill) 5318 { 5319 PISO9660RRIPRR pRR = (PISO9660RRIPRR)pbSys; 5320 Assert(cbSys >= sizeof(*pRR)); 5321 pRR->Hdr.bSig1 = ISO9660RRIPRR_SIG1; 5322 pRR->Hdr.bSig2 = ISO9660RRIPRR_SIG2; 5323 pRR->Hdr.cbEntry = ISO9660RRIPRR_LEN; 5324 pRR->Hdr.bVersion = ISO9660RRIPRR_VER; 5325 pRR->fFlags = pName->fRockEntries; 5326 pbSys += sizeof(*pRR); 5327 cbSys -= sizeof(*pRR); 5328 } 5329 5330 if (pName->fRockEntries & ISO9660RRIP_RR_F_PX) 5331 { 5332 PISO9660RRIPPX pPX = (PISO9660RRIPPX)pbSys; 5333 Assert(cbSys >= sizeof(*pPX)); 5334 pPX->Hdr.bSig1 = ISO9660RRIPPX_SIG1; 5335 pPX->Hdr.bSig2 = ISO9660RRIPPX_SIG2; 5336 pPX->Hdr.cbEntry = ISO9660RRIPPX_LEN; 5337 pPX->Hdr.bVersion = ISO9660RRIPPX_VER; 5338 pPX->fMode.be = RT_H2BE_U32((uint32_t)pName->fMode); 5339 pPX->fMode.le = RT_H2LE_U32((uint32_t)pName->fMode); 5340 pPX->cHardlinks.be = RT_H2BE_U32((uint32_t)pName->cHardlinks); 5341 pPX->cHardlinks.le = RT_H2LE_U32((uint32_t)pName->cHardlinks); 5342 pPX->uid.be = RT_H2BE_U32((uint32_t)pName->uid); 5343 pPX->uid.le = RT_H2LE_U32((uint32_t)pName->uid); 5344 pPX->gid.be = RT_H2BE_U32((uint32_t)pName->gid); 5345 pPX->gid.le = RT_H2LE_U32((uint32_t)pName->gid); 5346 pPX->INode.be = RT_H2BE_U32((uint32_t)pName->pObj->idxObj); 5347 pPX->INode.le = RT_H2LE_U32((uint32_t)pName->pObj->idxObj); 5348 pbSys += sizeof(*pPX); 5349 cbSys -= sizeof(*pPX); 5350 } 5351 5352 if (pName->fRockEntries & ISO9660RRIP_RR_F_TF) 5353 { 5354 PISO9660RRIPTF pTF = (PISO9660RRIPTF)pbSys; 5355 pTF->Hdr.bSig1 = ISO9660RRIPTF_SIG1; 5356 pTF->Hdr.bSig2 = ISO9660RRIPTF_SIG2; 5357 pTF->Hdr.cbEntry = Iso9660RripTfCalcLength(ISO9660RRIPTF_F_BIRTH | ISO9660RRIPTF_F_MODIFY | ISO9660RRIPTF_F_ACCESS | ISO9660RRIPTF_F_CHANGE); 5358 Assert(cbSys >= pTF->Hdr.cbEntry); 5359 pTF->Hdr.bVersion = ISO9660RRIPTF_VER; 5360 pTF->fFlags = ISO9660RRIPTF_F_BIRTH | ISO9660RRIPTF_F_MODIFY | ISO9660RRIPTF_F_ACCESS | ISO9660RRIPTF_F_CHANGE; 5361 PISO9660RECTIMESTAMP paTimestamps = (PISO9660RECTIMESTAMP)&pTF->abPayload[0]; 5362 rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->BirthTime, &paTimestamps[0]); 5363 rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->ModificationTime, &paTimestamps[1]); 5364 rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->AccessedTime, &paTimestamps[2]); 5365 rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->ChangeTime, &paTimestamps[3]); 5366 cbSys += pTF->Hdr.cbEntry; 5367 pbSys += pTF->Hdr.cbEntry; 5368 } 5369 5370 if (pName->fRockEntries & ISO9660RRIP_RR_F_PN) 5371 { 5372 PISO9660RRIPPN pPN = (PISO9660RRIPPN)pbSys; 5373 Assert(cbSys >= sizeof(*pPN)); 5374 pPN->Hdr.bSig1 = ISO9660RRIPPN_SIG1; 5375 pPN->Hdr.bSig2 = ISO9660RRIPPN_SIG2; 5376 pPN->Hdr.cbEntry = ISO9660RRIPPN_LEN; 5377 pPN->Hdr.bVersion = ISO9660RRIPPN_VER; 5378 pPN->Major.be = RT_H2BE_U32((uint32_t)RTDEV_MAJOR(pName->Device)); 5379 pPN->Major.le = RT_H2LE_U32((uint32_t)RTDEV_MAJOR(pName->Device)); 5380 pPN->Minor.be = RT_H2BE_U32((uint32_t)RTDEV_MINOR(pName->Device)); 5381 pPN->Minor.le = RT_H2LE_U32((uint32_t)RTDEV_MINOR(pName->Device)); 5382 } 5383 5384 if (pName->fRockEntries & ISO9660RRIP_RR_F_NM) 5385 { 5386 size_t cchSrc = pName->cchRockRidgeNm; 5387 const char *pszSrc = pName->pszRockRidgeNm; 5388 for (;;) 5389 { 5390 size_t cchThis = RT_MIN(cchSrc, ISO9660RRIPNM_MAX_NAME_LEN); 5391 PISO9660RRIPNM pNM = (PISO9660RRIPNM)pbSys; 5392 Assert(cbSys >= RT_OFFSETOF(ISO9660RRIPNM, achName[cchThis])); 5393 pNM->Hdr.bSig1 = ISO9660RRIPNM_SIG1; 5394 pNM->Hdr.bSig2 = ISO9660RRIPNM_SIG2; 5395 pNM->Hdr.cbEntry = (uint8_t)(RT_OFFSETOF(ISO9660RRIPNM, achName) + cchThis); 5396 pNM->Hdr.bVersion = ISO9660RRIPNM_VER; 5397 pNM->fFlags = cchThis == cchSrc ? 0 : ISO9660RRIP_NM_F_CONTINUE; 5398 memcpy(&pNM->achName[0], pszSrc, cchThis); 5399 pbSys += RT_OFFSETOF(ISO9660RRIPNM, achName) + cchThis; 5400 cbSys -= RT_OFFSETOF(ISO9660RRIPNM, achName) + cchThis; 5401 cchSrc -= cchThis; 5402 if (!cchSrc) 5403 break; 5404 } 5405 } 5406 5407 if (pName->fRockEntries & ISO9660RRIP_RR_F_SL) 5408 { 5409 AssertReturnVoid(pName->pObj->enmType == RTFSISOMAKEROBJTYPE_SYMLINK); 5410 PCRTFSISOMAKERSYMLINK pSymlink = (PCRTFSISOMAKERSYMLINK)pName->pObj; 5411 5412 ssize_t cbSlRockRidge = rtFsIsoMakerOutFile_RockRidgeGenSL(pSymlink->szTarget, pbSys, cbSys); 5413 AssertReturnVoid(cbSlRockRidge > 0); 5414 Assert(cbSys >= (size_t)cbSlRockRidge); 5415 cbSys -= (size_t)cbSlRockRidge; 5416 pbSys -= (size_t)cbSlRockRidge; 5417 } 5418 5419 /* finally, zero padding. */ 5420 if (cbSys & 1) 5421 { 5422 *pbSys++ = '\0'; 5423 cbSys--; 5424 } 5425 5426 Assert(cbSys == 0); 5427 } 5428 5429 5430 5431 5432 /** 5433 * Reads one or more sectors from a rock ridge spill file. 5434 * 5435 * @returns IPRT status code. 5436 * @param pThis The ISO maker output file instance. We use the 5437 * directory pointer hints and child index hints 5438 * @param pIsoMaker The ISO maker. 5439 * @param pFile The rock ridge spill file. 5440 * @param offInFile The offset into the spill file. This is sector aligned. 5441 * @param pbBuf The output buffer. 5442 * @param cbToRead The number of bytes to tread. This is sector aligned. 5443 */ 5444 static int rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERINT pIsoMaker, 5445 PRTFSISOMAKERFILE pFile, uint32_t offInFile, uint8_t *pbBuf, 5446 size_t cbToRead) 5447 { 5448 /* 5449 * We're only working multiple of ISO 9660 sectors. 5450 * 5451 * The spill of one directory record will always fit entirely within a 5452 * sector, we make sure about that during finalization. There may be 5453 * zero padding between spill data sequences, especially on the sector 5454 * boundrary. 5455 */ 5456 Assert((offInFile & ISO9660_SECTOR_OFFSET_MASK) == 0); 5457 Assert((cbToRead & ISO9660_SECTOR_OFFSET_MASK) == 0); 5458 Assert(cbToRead >= ISO9660_SECTOR_SIZE); 5459 5460 /* 5461 * We generate a sector at a time. 5462 * 5463 * So, we start by locating the first directory/child in the block offInFile 5464 * is pointing to. 5465 */ 5466 PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs; 5467 PRTFSISOMAKERNAMEDIR *ppDirHint; 5468 uint32_t *pidxChildHint; 5469 if (pFile->u.pRockSpillNamespace->fNamespace & RTFSISOMAKER_NAMESPACE_ISO_9660) 5470 { 5471 pFinalizedDirs = &pIsoMaker->PrimaryIsoDirs; 5472 ppDirHint = &pThis->pDirHintPrimaryIso; 5473 pidxChildHint = &pThis->iChildPrimaryIso; 5474 } 5475 else 5476 { 5477 pFinalizedDirs = &pIsoMaker->JolietDirs; 5478 ppDirHint = &pThis->pDirHintJoliet; 5479 pidxChildHint = &pThis->iChildJoliet; 5480 } 5481 5482 /* Special case: '.' record in root dir */ 5483 uint32_t idxChild = *pidxChildHint; 5484 PRTFSISOMAKERNAMEDIR pDir = *ppDirHint; 5485 if ( offInFile == 0 5486 && (pDir = RTListGetFirst(&pFinalizedDirs->FinalizedDirs, RTFSISOMAKERNAMEDIR, FinalizedEntry)) != NULL 5487 && pDir->pName->cbRockSpill > 0) 5488 { 5489 AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ); 5490 AssertReturn(pDir->pName->offRockSpill == 0, VERR_ISOMK_IPE_RR_READ); 5491 idxChild = 0; 5492 } 5493 else 5494 { 5495 /* Establish where to start searching from. */ 5496 if ( !pDir 5497 || idxChild >= pDir->cChildren 5498 || pDir->papChildren[idxChild]->cbRockSpill == 0) 5499 { 5500 idxChild = 0; 5501 pDir = RTListGetFirst(&pFinalizedDirs->FinalizedDirs, RTFSISOMAKERNAMEDIR, FinalizedEntry); 5502 AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ); 5503 } 5504 5505 if (pDir->papChildren[idxChild]->offRockSpill == offInFile) 5506 { /* hit, no need to search */ } 5507 else if (pDir->papChildren[idxChild]->offRockSpill < offInFile) 5508 { 5509 /* search forwards */ 5510 for (;;) 5511 { 5512 idxChild++; 5513 while ( idxChild < pDir->cChildren 5514 && ( pDir->papChildren[idxChild]->offRockSpill < offInFile 5515 || pDir->papChildren[idxChild]->cbRockSpill == 0) ) 5516 idxChild++; 5517 if (idxChild < pDir->cChildren) 5518 break; 5519 pDir = RTListGetNext(&pFinalizedDirs->FinalizedDirs, pDir, RTFSISOMAKERNAMEDIR, FinalizedEntry); 5520 AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ); 5521 } 5522 Assert(pDir->papChildren[idxChild]->offRockSpill == offInFile); 5523 } 5524 else 5525 { 5526 /* search backwards (no root dir concerns here) */ 5527 for (;;) 5528 { 5529 while ( idxChild > 0 5530 && ( pDir->papChildren[idxChild - 1]->offRockSpill >= offInFile 5531 || pDir->papChildren[idxChild - 1]->cbRockSpill == 0) ) 5532 idxChild--; 5533 if (pDir->papChildren[idxChild]->offRockSpill == offInFile) 5534 break; 5535 pDir = RTListGetPrev(&pFinalizedDirs->FinalizedDirs, pDir, RTFSISOMAKERNAMEDIR, FinalizedEntry); 5536 AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ); 5537 } 5538 Assert(pDir->papChildren[idxChild]->offRockSpill == offInFile); 5539 } 5540 } 5541 5542 /* 5543 * Produce data. 5544 */ 5545 while (cbToRead > 0) 5546 { 5547 PRTFSISOMAKERNAME pChild; 5548 if ( offInFile > 0 5549 || pDir->pName->cbRockSpill == 0 5550 || pDir->pName->pParent != NULL) 5551 { 5552 pChild = pDir->papChildren[idxChild]; 5553 AssertReturn(pChild->offRockSpill == offInFile, VERR_ISOMK_IPE_RR_READ); 5554 AssertReturn(pChild->cbRockSpill > 0, VERR_ISOMK_IPE_RR_READ); 5555 idxChild++; 5556 } 5557 else 5558 { /* root dir special case. */ 5559 pChild = pDir->pName; 5560 Assert(idxChild == 0); 5561 Assert(pChild->pParent == NULL); 5562 } 5563 5564 AssertReturn(cbToRead >= pChild->cbRockSpill, VERR_ISOMK_IPE_RR_READ); 5565 rtFsIosMakerOutFile_GenerateRockRidge(pDir->pName, pbBuf, cbToRead, true /*fInSpill*/); 5566 cbToRead -= pChild->cbRockSpill; 5567 pbBuf += pChild->cbRockSpill; 5568 offInFile += pChild->cbRockSpill; 5569 5570 /* Advance to the next name, if any. */ 5571 uint32_t offNext = UINT32_MAX; 5572 do 5573 { 5574 while (idxChild < pDir->cChildren) 5575 { 5576 pChild = pDir->papChildren[idxChild]; 5577 if (pChild->cbRockSpill == 0) 5578 Assert(pChild->offRockSpill == UINT32_MAX); 5579 else 5580 { 5581 offNext = pChild->offRockSpill; 5582 AssertReturn(offNext >= offInFile, VERR_ISOMK_IPE_RR_READ); 5583 AssertReturn(offNext < pFile->cbData, VERR_ISOMK_IPE_RR_READ); 5584 break; 5585 } 5586 idxChild++; 5587 } 5588 pDir = RTListGetNext(&pFinalizedDirs->FinalizedDirs, pDir, RTFSISOMAKERNAMEDIR, FinalizedEntry); 5589 idxChild = 0; 5590 } while (pDir != NULL); 5591 5592 if (offNext != UINT32_MAX) 5593 { 5594 uint32_t cbToZero = offNext - offInFile; 5595 if (cbToRead > cbToZero) 5596 RT_BZERO(pbBuf, cbToZero); 5597 else 5598 { 5599 RT_BZERO(pbBuf, cbToRead); 5600 *ppDirHint = pDir; 5601 *pidxChildHint = idxChild; 5602 break; 5603 } 5604 } 5605 else 5606 { 5607 RT_BZERO(pbBuf, cbToRead); 5608 *ppDirHint = NULL; 5609 *pidxChildHint = UINT32_MAX; 5610 break; 5611 } 5612 } 5613 5614 return VINF_SUCCESS; 5615 } 5616 5617 5618 /** 5619 * Deals with reads that aren't an exact multiple of sectors. 5620 * 5621 * @returns IPRT status code. 5622 * @param pThis The ISO maker output file instance. We use the 5623 * directory pointer hints and child index hints 5624 * @param pIsoMaker The ISO maker. 5625 * @param pFile The rock ridge spill file. 5626 * @param offInFile The offset into the spill file. 5627 * @param pbBuf The output buffer. 5628 * @param cbToRead The number of bytes to tread. 5629 */ 5630 static int rtFsIsoMakerOutFile_RockRidgeSpillReadUnaligned(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERINT pIsoMaker, 5631 PRTFSISOMAKERFILE pFile, uint32_t offInFile, uint8_t *pbBuf, 5632 uint32_t cbToRead) 5633 { 5634 for (;;) 5635 { 5636 /* 5637 * Deal with unnaligned file offsets and sub-sector sized reads. 5638 */ 5639 if ( (offInFile & ISO9660_SECTOR_OFFSET_MASK) 5640 || cbToRead < ISO9660_SECTOR_SIZE) 5641 { 5642 uint8_t abSectorBuf[ISO9660_SECTOR_SIZE]; 5643 int rc = rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(pThis, pIsoMaker, pFile, 5644 offInFile & ~(uint32_t)ISO9660_SECTOR_OFFSET_MASK, 5645 abSectorBuf, sizeof(abSectorBuf)); 5646 if (RT_FAILURE(rc)) 5647 return rc; 5648 uint32_t offSrcBuf = (size_t)offInFile & (size_t)ISO9660_SECTOR_OFFSET_MASK; 5649 uint32_t cbToCopy = RT_MIN(ISO9660_SECTOR_SIZE - offSrcBuf, cbToRead); 5650 memcpy(pbBuf, &abSectorBuf[offSrcBuf], cbToCopy); 5651 if (cbToCopy >= cbToRead) 5652 return VINF_SUCCESS; 5653 cbToRead -= cbToCopy; 5654 offInFile += cbToCopy; 5655 pbBuf += cbToCopy; 5656 } 5657 5658 /* 5659 * The offset is aligned now, so try read some sectors directly into the buffer. 5660 */ 5661 AssertContinue((offInFile & ISO9660_SECTOR_OFFSET_MASK) == 0); 5662 if (cbToRead >= ISO9660_SECTOR_SIZE) 5663 { 5664 uint32_t cbFullSectors = cbToRead & ~(uint32_t)ISO9660_SECTOR_OFFSET_MASK; 5665 int rc = rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(pThis, pIsoMaker, pFile, offInFile, pbBuf, cbFullSectors); 5666 if (RT_FAILURE(rc)) 5667 return rc; 5668 if (cbFullSectors >= cbToRead) 5669 return VINF_SUCCESS; 5670 cbToRead -= cbFullSectors; 5671 offInFile += cbFullSectors; 5672 pbBuf += cbFullSectors; 5673 } 5674 } 5675 } 5676 5677 5678 5679 /** 4952 5680 * Produces the content of a TRANS.TBL file as a memory file. 4953 5681 * … … 5003 5731 AssertMsgFailed(("rc=%Rrc, cbResult=%#RX64 cbData=%#RX64\n", rc, cbResult, pFile->cbData)); 5004 5732 RTVfsFileRelease(hVfsFile); 5005 return VERR_I NTERNAL_ERROR_4;5733 return VERR_ISOMK_IPE_PRODUCE_TRANS_TBL; 5006 5734 } 5007 5735 … … 5034 5762 { 5035 5763 pFile = RTListGetFirst(&pIsoMaker->FinalizedFiles, RTFSISOMAKERFILE, FinalizedEntry); 5036 AssertReturn(pFile, VERR_I NTERNAL_ERROR_2);5764 AssertReturn(pFile, VERR_ISOMK_IPE_READ_FILE_DATA_1); 5037 5765 } 5038 5766 if ((offInFile = offUnsigned - pFile->offData) < RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE)) … … 5044 5772 { 5045 5773 pFile = RTListGetNext(&pIsoMaker->FinalizedFiles, pFile, RTFSISOMAKERFILE, FinalizedEntry); 5046 AssertReturn(pFile, VERR_I NTERNAL_ERROR_3);5774 AssertReturn(pFile, VERR_ISOMK_IPE_READ_FILE_DATA_2); 5047 5775 } while ((offInFile = offUnsigned - pFile->offData) >= RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE)); 5048 5776 } … … 5053 5781 { 5054 5782 pFile = RTListGetPrev(&pIsoMaker->FinalizedFiles, pFile, RTFSISOMAKERFILE, FinalizedEntry); 5055 AssertReturn(pFile, VERR_I NTERNAL_ERROR_3);5783 AssertReturn(pFile, VERR_ISOMK_IPE_READ_FILE_DATA_3); 5056 5784 } while ((offInFile = offUnsigned - pFile->offData) >= RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE)); 5057 5785 } … … 5112 5840 break; 5113 5841 5842 case RTFSISOMAKERSRCTYPE_RR_SPILL: 5843 Assert(pFile->cbData < UINT32_MAX); 5844 if ( !(offInFile & ISO9660_SECTOR_OFFSET_MASK) 5845 && !(cbToRead & ISO9660_SECTOR_OFFSET_MASK) 5846 && cbToRead > 0) 5847 rc = rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(pThis, pIsoMaker, pFile, (uint32_t)offInFile, 5848 pbBuf, (uint32_t)cbToRead); 5849 else 5850 rc = rtFsIsoMakerOutFile_RockRidgeSpillReadUnaligned(pThis, pIsoMaker, pFile, (uint32_t)offInFile, 5851 pbBuf, (uint32_t)cbToRead); 5852 break; 5853 5114 5854 default: 5115 AssertFailedReturn(VERR_I NTERNAL_ERROR_5);5855 AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE); 5116 5856 } 5117 5857 if (RT_FAILURE(rc)) … … 5319 6059 * 5320 6060 * @returns Number of bytes copied into the buffer (pName->cbDirRec). 5321 * @param pName The namespace node. 5322 * @param fUnicode Set if the name should be translated to big endian 5323 * UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace. 5324 * @param pbBuf The buffer. This is at least pName->cbDirRec bytes big 5325 * (i.e. at most 256 bytes). 5326 */ 5327 static uint32_t rtFsIsoMakerOutFile_GenerateDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf) 6061 * @param pName The namespace node. 6062 * @param fUnicode Set if the name should be translated to big endian 6063 * UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace. 6064 * @param pbBuf The buffer. This is at least pName->cbDirRec bytes 6065 * big (i.e. at most 256 bytes). 6066 * @param pFinalizedDirs The finalized directory data for the namespace. 6067 */ 6068 static uint32_t rtFsIsoMakerOutFile_GenerateDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf, 6069 PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs) 5328 6070 { 5329 6071 /* … … 5392 6134 * Rock ridge fields if enabled. 5393 6135 */ 5394 /** @todo rock ridge. */ 6136 if (pName->cbRockInDirRec > 0) 6137 { 6138 uint8_t *pbSys = (uint8_t *)&pDirRec->achFileId[pName->cbNameInDirRec + !(pName->cbNameInDirRec & 1)]; 6139 size_t cbSys = &pbBuf[pName->cbDirRec] - pbSys; 6140 Assert(cbSys >= pName->cbRockInDirRec); 6141 if (cbSys > pName->cbRockInDirRec) 6142 RT_BZERO(&pbSys[pName->cbRockInDirRec], cbSys - pName->cbRockInDirRec); 6143 if (pName->cbRockSpill == 0) 6144 rtFsIosMakerOutFile_GenerateRockRidge(pName, pbSys, cbSys, false /*fInSpill*/); 6145 else 6146 { 6147 /* Maybe emit SP and RR entry, before emitting the CE entry. */ 6148 if (pName->pParent == NULL) 6149 { 6150 PISO9660SUSPSP pSP = (PISO9660SUSPSP)pbSys; 6151 pSP->Hdr.bSig1 = ISO9660SUSPSP_SIG1; 6152 pSP->Hdr.bSig2 = ISO9660SUSPSP_SIG2; 6153 pSP->Hdr.cbEntry = ISO9660SUSPSP_LEN; 6154 pSP->Hdr.bVersion = ISO9660SUSPSP_VER; 6155 pSP->bCheck1 = ISO9660SUSPSP_CHECK1; 6156 pSP->bCheck2 = ISO9660SUSPSP_CHECK2; 6157 pSP->cbSkip = 0; 6158 pbSys += sizeof(*pSP); 6159 cbSys -= sizeof(*pSP); 6160 } 6161 if (pName->fRockNeedRRInDirRec) 6162 { 6163 PISO9660RRIPRR pRR = (PISO9660RRIPRR)pbSys; 6164 pRR->Hdr.bSig1 = ISO9660RRIPRR_SIG1; 6165 pRR->Hdr.bSig2 = ISO9660RRIPRR_SIG2; 6166 pRR->Hdr.cbEntry = ISO9660RRIPRR_LEN; 6167 pRR->Hdr.bVersion = ISO9660RRIPRR_VER; 6168 pRR->fFlags = pName->fRockEntries; 6169 pbSys += sizeof(*pRR); 6170 cbSys -= sizeof(*pRR); 6171 } 6172 PISO9660SUSPCE pCE = (PISO9660SUSPCE)pbSys; 6173 pCE->Hdr.bSig1 = ISO9660SUSPCE_SIG1; 6174 pCE->Hdr.bSig2 = ISO9660SUSPCE_SIG2; 6175 pCE->Hdr.cbEntry = ISO9660SUSPCE_LEN; 6176 pCE->Hdr.bVersion = ISO9660SUSPCE_VER; 6177 uint64_t offData = pFinalizedDirs->pRRSpillFile->offData + pName->offRockSpill; 6178 pCE->offBlock.be = RT_H2BE_U32((uint32_t)(offData / ISO9660_SECTOR_SIZE)); 6179 pCE->offBlock.le = RT_H2LE_U32((uint32_t)(offData / ISO9660_SECTOR_SIZE)); 6180 pCE->offData.be = RT_H2BE_U32((uint32_t)(offData & ISO9660_SECTOR_OFFSET_MASK)); 6181 pCE->offData.le = RT_H2LE_U32((uint32_t)(offData & ISO9660_SECTOR_OFFSET_MASK)); 6182 pCE->cbData.be = RT_H2BE_U32((uint32_t)pName->cbRockSpill); 6183 pCE->cbData.le = RT_H2LE_U32((uint32_t)pName->cbRockSpill); 6184 Assert(cbSys >= sizeof(*pCE)); 6185 } 6186 } 5395 6187 5396 6188 return pName->cbDirRec; … … 5402 6194 * 5403 6195 * @returns Number of bytes copied into the buffer. 5404 * @param pName The namespace node. 5405 * @param fUnicode Set if the name should be translated to big endian 5406 * UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace. 5407 * @param pbBuf The buffer. This is at least pName->cbDirRecTotal bytes 5408 * big. 5409 */ 5410 static uint32_t rtFsIsoMakerOutFile_GenerateDirRecDirect(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf) 6196 * @param pName The namespace node. 6197 * @param fUnicode Set if the name should be translated to big endian 6198 * UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace. 6199 * @param pbBuf The buffer. This is at least pName->cbDirRecTotal 6200 * bytes big. 6201 * @param pFinalizedDirs The finalized directory data for the namespace. 6202 */ 6203 static uint32_t rtFsIsoMakerOutFile_GenerateDirRecDirect(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf, 6204 PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs) 5411 6205 { 5412 6206 /* 5413 6207 * Normally there is just a single record without any zero padding. 5414 6208 */ 5415 uint32_t cbReturn = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf );6209 uint32_t cbReturn = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf, pFinalizedDirs); 5416 6210 if (RT_LIKELY(pName->cbDirRecTotal == cbReturn)) 5417 6211 return cbReturn; … … 5470 6264 * 5471 6265 * @returns Number of bytes copied into the buffer. 5472 * @param pName The namespace node. 5473 * @param fUnicode Set if the name should be translated to big endian 5474 * UTF-16 / UCS-2, i.e. we're in the joliet namespace. 5475 * @param off The offset into the directory record. 5476 * @param pbBuf The buffer. 5477 * @param cbBuf The buffer size. 6266 * @param pName The namespace node. 6267 * @param fUnicode Set if the name should be translated to big endian 6268 * UTF-16 / UCS-2, i.e. we're in the joliet namespace. 6269 * @param off The offset into the directory record. 6270 * @param pbBuf The buffer. 6271 * @param cbBuf The buffer size. 6272 * @param pFinalizedDirs The finalized directory data for the namespace. 5478 6273 */ 5479 6274 static uint32_t rtFsIsoMakerOutFile_GenerateDirRecPartial(PRTFSISOMAKERNAME pName, bool fUnicode, 5480 uint32_t off, uint8_t *pbBuf, size_t cbBuf) 6275 uint32_t off, uint8_t *pbBuf, size_t cbBuf, 6276 PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs) 5481 6277 { 5482 6278 Assert(off < pName->cbDirRecTotal); … … 5488 6284 uint8_t abTmpBuf[256]; 5489 6285 Assert(pName->cbDirRec <= sizeof(abTmpBuf)); 5490 uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf );6286 uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf, pFinalizedDirs); 5491 6287 Assert(cbOne == pName->cbDirRec); 5492 6288 if (cbOne == pName->cbDirRecTotal) … … 5588 6384 * 5589 6385 * @returns Number of bytes copied into the buffer. 5590 * @param pName The directory namespace node. 5591 * @param fUnicode Set if the name should be translated to big endian 5592 * UTF-16 / UCS-2, i.e. we're in the joliet namespace. 5593 * @param bDirId The directory ID (0x00 or 0x01). 5594 * @param off The offset into the directory record. 5595 * @param pbBuf The buffer. 5596 * @param cbBuf The buffer size. 6386 * @param pName The directory namespace node. 6387 * @param fUnicode Set if the name should be translated to big endian 6388 * UTF-16 / UCS-2, i.e. we're in the joliet namespace. 6389 * @param bDirId The directory ID (0x00 or 0x01). 6390 * @param off The offset into the directory record. 6391 * @param pbBuf The buffer. 6392 * @param cbBuf The buffer size. 6393 * @param pFinalizedDirs The finalized directory data for the namespace. 5597 6394 */ 5598 6395 static uint32_t rtFsIsoMakerOutFile_GenerateSpecialDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t bDirId, 5599 uint32_t off, uint8_t *pbBuf, size_t cbBuf) 6396 uint32_t off, uint8_t *pbBuf, size_t cbBuf, 6397 PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs) 5600 6398 { 5601 6399 Assert(off < pName->cbDirRec); … … 5605 6403 uint8_t abTmpBuf[256]; 5606 6404 Assert(off < pName->cbDirRec); 5607 size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf );6405 size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf, pFinalizedDirs); 5608 6406 Assert(cbToCopy == pName->cbDirRec); 5609 6407 … … 5707 6505 if (offInDir < pDir->cbDirRec00) 5708 6506 { 5709 uint32_t cbCopied = rtFsIsoMakerOutFile_GenerateSpecialDirRec(pDirName, fUnicode, 0, offInDir, pbBuf, cbBuf); 6507 uint32_t cbCopied = rtFsIsoMakerOutFile_GenerateSpecialDirRec(pDirName, fUnicode, 0, offInDir, 6508 pbBuf, cbBuf, pFinalizedDirs); 5710 6509 cbDone += cbCopied; 5711 6510 offInDir += cbCopied; … … 5718 6517 { 5719 6518 uint32_t cbCopied = rtFsIsoMakerOutFile_GenerateSpecialDirRec(pParentName, fUnicode, 1, 5720 offInDir - pDir->cbDirRec00, pbBuf, cbBuf); 6519 offInDir - pDir->cbDirRec00, 6520 pbBuf, cbBuf, pFinalizedDirs); 5721 6521 cbDone += cbCopied; 5722 6522 offInDir += cbCopied; … … 5755 6555 if ( offInDir == pChild->offDirRec 5756 6556 && cbBuf >= pChild->cbDirRecTotal) 5757 cbCopied = rtFsIsoMakerOutFile_GenerateDirRecDirect(pChild, fUnicode, pbBuf );6557 cbCopied = rtFsIsoMakerOutFile_GenerateDirRecDirect(pChild, fUnicode, pbBuf, pFinalizedDirs); 5758 6558 else 5759 cbCopied = rtFsIsoMakerOutFile_GenerateDirRecPartial(pChild, fUnicode, offInDir - pChild->offDirRec, pbBuf, cbBuf); 6559 cbCopied = rtFsIsoMakerOutFile_GenerateDirRecPartial(pChild, fUnicode, offInDir - pChild->offDirRec, 6560 pbBuf, cbBuf, pFinalizedDirs); 5760 6561 5761 6562 cbDone += cbCopied; … … 5904 6705 cbDone = rtFsIsoMakerOutFile_ReadDirStructures(&pThis->pDirHintPrimaryIso, &pIsoMaker->PrimaryIso, 5905 6706 &pIsoMaker->PrimaryIsoDirs, offUnsigned, pbBuf, cbBuf); 5906 /** @todo Insert El Torito stuff here? Probably okay to let it be in the file5907 * area, right? */5908 6707 /* 5909 6708 * Volume descriptors. … … 6056 6855 6057 6856 default: 6058 return VERR_IN TERNAL_ERROR_5;6857 return VERR_INVALID_PARAMETER; 6059 6858 } 6060 6859 … … 6169 6968 pFileData->pDirHintPrimaryIso = NULL; 6170 6969 pFileData->pDirHintJoliet = NULL; 6970 pFileData->iChildPrimaryIso = UINT32_MAX; 6971 pFileData->iChildJoliet = UINT32_MAX; 6171 6972 *phVfsFile = hVfsFile; 6172 6973 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.