Changeset 67437 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Jun 16, 2017 1:14:39 PM (7 years ago)
- Location:
- trunk/src/VBox/Runtime/common/fs
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/isomaker.cpp
r67427 r67437 55 55 *********************************************************************************************************************************/ 56 56 /** Asserts valid handle, returns @a a_rcRet if not. */ 57 #define RTFSISOMAKER_ASSER _VALID_HANDLE_RET_EX(a_pThis, a_rcRet) \57 #define RTFSISOMAKER_ASSERT_VALID_HANDLE_RET_EX(a_pThis, a_rcRet) \ 58 58 do { AssertPtrReturn(a_pThis, a_rcRet); \ 59 59 AssertReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, a_rcRet); \ … … 61 61 62 62 /** Asserts valid handle, returns VERR_INVALID_HANDLE if not. */ 63 #define RTFSISOMAKER_ASSER _VALID_HANDLE_RET(a_pThis) RTFSISOMAKER_ASSER_VALID_HANDLE_RET_EX(a_pThis, VERR_INVALID_HANDLE)63 #define RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(a_pThis) RTFSISOMAKER_ASSERT_VALID_HANDLE_RET_EX(a_pThis, VERR_INVALID_HANDLE) 64 64 65 65 /** The sector size. */ … … 374 374 } u; 375 375 376 /** Boot info table to patch into the file. 377 * This is calculated during file finalization as it needs the file location. */ 378 PISO9660SYSLINUXINFOTABLE pBootInfoTable; 379 376 380 /** Entry in the list of finalized directories. */ 377 381 RTLISTNODE FinalizedEntry; … … 446 450 /** The default file mode mask. */ 447 451 RTFMODE fDefaultDirMode; 452 453 /** @name Boot related stuff 454 * @{ */ 455 /** The boot catalog file. */ 456 PRTFSISOMAKERFILE pBootCatFile; 457 458 /** @} */ 448 459 449 460 /** @name Finalized image stuff … … 728 739 pThis->fDefaultDirMode = 0555 | RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY | RTFS_DOS_READONLY; 729 740 741 //pThis->pBootCatFile = NULL; 742 730 743 pThis->cbFinalizedImage = UINT64_MAX; 731 744 //pThis->pbSysArea = NULL; … … 807 820 808 821 /* no default, want warnings */ 822 } 823 if (pFile->pBootInfoTable) 824 { 825 RTMemFree(pFile->pBootInfoTable); 826 pFile->pBootInfoTable = NULL; 809 827 } 810 828 } … … 1027 1045 { 1028 1046 PRTFSISOMAKERINT pThis = hIsoMaker; 1029 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);1047 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 1030 1048 AssertReturn(uIsoLevel <= 3, VERR_INVALID_PARAMETER); 1031 1049 AssertReturn(uIsoLevel > 0, VERR_INVALID_PARAMETER); /* currently not possible to disable this */ … … 1048 1066 { 1049 1067 PRTFSISOMAKERINT pThis = hIsoMaker; 1050 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);1068 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 1051 1069 AssertReturn(uJolietLevel <= 3, VERR_INVALID_PARAMETER); 1052 1070 AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER); … … 1075 1093 { 1076 1094 PRTFSISOMAKERINT pThis = hIsoMaker; 1077 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);1095 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 1078 1096 AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER); 1079 1097 AssertReturn(uLevel <= 2, VERR_INVALID_PARAMETER); … … 1095 1113 { 1096 1114 PRTFSISOMAKERINT pThis = hIsoMaker; 1097 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);1115 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 1098 1116 AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER); 1099 1117 AssertReturn(uLevel <= 2, VERR_INVALID_PARAMETER); … … 1124 1142 */ 1125 1143 PRTFSISOMAKERINT pThis = hIsoMaker; 1126 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);1144 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 1127 1145 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 1128 1146 AssertReturn(cbContent > 0, VERR_OUT_OF_RANGE); … … 1723 1741 pFile->enmSrcType = RTFSISOMAKERSRCTYPE_TRANS_TBL; 1724 1742 pFile->u.pTransTblDir = pDirName; 1743 pFile->pBootInfoTable = NULL; 1725 1744 pDirName->pDir->pTransTblFile = pFile; 1726 1745 … … 2245 2264 */ 2246 2265 PRTFSISOMAKERINT pThis = hIsoMaker; 2247 RTFSISOMAKER_ASSER _VALID_HANDLE_RET_EX(pThis, UINT32_MAX);2266 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET_EX(pThis, UINT32_MAX); 2248 2267 2249 2268 /* … … 2323 2342 */ 2324 2343 PRTFSISOMAKERINT pThis = hIsoMaker; 2325 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2344 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2326 2345 PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj); 2327 2346 AssertReturn(pObj, VERR_OUT_OF_RANGE); … … 2356 2375 */ 2357 2376 PRTFSISOMAKERINT pThis = hIsoMaker; 2358 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2377 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2359 2378 AssertReturn(!(fNamespaces & ~RTFSISOMAKER_NAMESPACE_VALID_MASK), VERR_INVALID_FLAGS); 2360 2379 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); … … 2405 2424 */ 2406 2425 PRTFSISOMAKERINT pThis = hIsoMaker; 2407 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2426 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2408 2427 AssertReturn(!(fNamespaces & ~RTFSISOMAKER_NAMESPACE_VALID_MASK), VERR_INVALID_FLAGS); 2409 2428 AssertPtrReturn(pszName, VERR_INVALID_POINTER); … … 2442 2461 2443 2462 /** 2463 * Enables or disable syslinux boot info table patching of a file. 2464 * 2465 * @returns IPRT status code. 2466 * @param hIsoMaker The ISO maker handle. 2467 * @param idxObj The configuration index. 2468 * @param fEnable Whether to enable or disable patching. 2469 */ 2470 RTDECL(int) RTFsIsoMakerObjEnableBootInfoTablePatching(RTFSISOMAKER hIsoMaker, uint32_t idxObj, bool fEnable) 2471 { 2472 /* 2473 * Validate and translate input. 2474 */ 2475 PRTFSISOMAKERINT pThis = hIsoMaker; 2476 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2477 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 2478 PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj); 2479 AssertReturn(pObj, VERR_OUT_OF_RANGE); 2480 AssertReturn(pObj->enmType == RTFSISOMAKEROBJTYPE_FILE, VERR_WRONG_TYPE); 2481 PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pObj; 2482 AssertReturn( pFile->enmSrcType == RTFSISOMAKERSRCTYPE_PATH 2483 || pFile->enmSrcType == RTFSISOMAKERSRCTYPE_VFS_FILE, 2484 VERR_WRONG_TYPE); 2485 2486 /* 2487 * Do the job. 2488 */ 2489 if (fEnable) 2490 { 2491 if (!pFile->pBootInfoTable) 2492 { 2493 pFile->pBootInfoTable = (PISO9660SYSLINUXINFOTABLE)RTMemAllocZ(sizeof(*pFile->pBootInfoTable)); 2494 AssertReturn(pFile->pBootInfoTable, VERR_NO_MEMORY); 2495 } 2496 } 2497 else if (pFile->pBootInfoTable) 2498 { 2499 RTMemFree(pFile->pBootInfoTable); 2500 pFile->pBootInfoTable = NULL; 2501 } 2502 return VINF_SUCCESS; 2503 } 2504 2505 2506 /** 2507 * Gets the data size of an object. 2508 * 2509 * Currently only supported on file objects. 2510 * 2511 * @returns IPRT status code. 2512 * @param hIsoMaker The ISO maker handle. 2513 * @param idxObj The configuration index. 2514 * @param pcbData Where to return the size. 2515 */ 2516 RTDECL(int) RTFsIsoMakerObjQueryDataSize(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint64_t *pcbData) 2517 { 2518 /* 2519 * Validate and translate input. 2520 */ 2521 AssertPtrReturn(pcbData, VERR_INVALID_POINTER); 2522 *pcbData = UINT64_MAX; 2523 PRTFSISOMAKERINT pThis = hIsoMaker; 2524 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2525 PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj); 2526 AssertReturn(pObj, VERR_OUT_OF_RANGE); 2527 2528 /* 2529 * Do the job. 2530 */ 2531 if (pObj->enmType == RTFSISOMAKEROBJTYPE_FILE) 2532 { 2533 PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pObj; 2534 if (pFile->enmSrcType != RTFSISOMAKERSRCTYPE_TRANS_TBL) 2535 { 2536 *pcbData = ((PRTFSISOMAKERFILE)pObj)->cbData; 2537 return VINF_SUCCESS; 2538 } 2539 } 2540 return VERR_WRONG_TYPE; 2541 } 2542 2543 2544 /** 2444 2545 * Initalizes the common part of a file system object and links it into global 2445 2546 * chain. … … 2528 2629 { 2529 2630 PRTFSISOMAKERINT pThis = hIsoMaker; 2530 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2631 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2531 2632 AssertPtrReturn(pidxObj, VERR_INVALID_POINTER); 2532 2633 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); … … 2553 2654 { 2554 2655 PRTFSISOMAKERINT pThis = hIsoMaker; 2555 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2656 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2556 2657 AssertPtrReturn(pszDir, VERR_INVALID_POINTER); 2557 2658 AssertReturn(RTPATH_IS_SLASH(*pszDir), VERR_INVALID_NAME); … … 2579 2680 * @returns IPRT status code. 2580 2681 * @param pThis The ISO make instance. 2682 * @param pObjInfo Object information. Optional. 2581 2683 * @param cbExtra Extra space for additional data (e.g. source 2582 2684 * path string copy). … … 2622 2724 { 2623 2725 PRTFSISOMAKERINT pThis = hIsoMaker; 2624 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2726 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2625 2727 AssertPtrReturn(pidxObj, VERR_INVALID_POINTER); 2626 2728 *pidxObj = UINT32_MAX; … … 2644 2746 if (RT_SUCCESS(rc)) 2645 2747 { 2646 pFile->enmSrcType = RTFSISOMAKERSRCTYPE_PATH; 2647 pFile->u.pszSrcPath = (char *)memcpy(pFile + 1, pszSrcFile, cbSrcFile); 2748 pFile->enmSrcType = RTFSISOMAKERSRCTYPE_PATH; 2749 pFile->u.pszSrcPath = (char *)memcpy(pFile + 1, pszSrcFile, cbSrcFile); 2750 pFile->pBootInfoTable = NULL; 2648 2751 2649 2752 *pidxObj = pFile->Core.idxObj; … … 2668 2771 { 2669 2772 PRTFSISOMAKERINT pThis = hIsoMaker; 2670 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2773 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2671 2774 AssertPtrReturn(pidxObj, VERR_INVALID_POINTER); 2672 2775 *pidxObj = UINT32_MAX; … … 2693 2796 if (RT_SUCCESS(rc)) 2694 2797 { 2695 pFile->enmSrcType = RTFSISOMAKERSRCTYPE_VFS_FILE; 2696 pFile->u.hVfsFile = hVfsFileSrc; 2798 pFile->enmSrcType = RTFSISOMAKERSRCTYPE_VFS_FILE; 2799 pFile->u.hVfsFile = hVfsFileSrc; 2800 pFile->pBootInfoTable = NULL; 2697 2801 2698 2802 *pidxObj = pFile->Core.idxObj; … … 2720 2824 { 2721 2825 PRTFSISOMAKERINT pThis = hIsoMaker; 2722 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2826 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2723 2827 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 2724 2828 AssertReturn(RTPATH_IS_SLASH(*pszFile), VERR_INVALID_NAME); … … 2757 2861 { 2758 2862 PRTFSISOMAKERINT pThis = hIsoMaker; 2759 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);2863 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2760 2864 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 2761 2865 AssertReturn(RTPATH_IS_SLASH(*pszFile), VERR_INVALID_NAME); … … 2777 2881 } 2778 2882 2883 2884 2885 2886 /* 2887 * 2888 * El Torito Booting. 2889 * El Torito Booting. 2890 * El Torito Booting. 2891 * El Torito Booting. 2892 * 2893 */ 2894 2895 /** 2896 * Ensures that we've got a boot catalog file. 2897 * 2898 * @returns IPRT status code. 2899 * @param pThis The ISO maker instance. 2900 */ 2901 static int rtFsIsoMakerEnsureBootCatFile(PRTFSISOMAKERINT pThis) 2902 { 2903 if (pThis->pBootCatFile) 2904 return VINF_SUCCESS; 2905 2906 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 2907 2908 /* Create a VFS memory file for backing up the file. */ 2909 RTVFSFILE hVfsFile; 2910 int rc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, RTFSISOMAKER_SECTOR_SIZE, &hVfsFile); 2911 if (RT_SUCCESS(rc)) 2912 { 2913 /* Create an unnamed VFS backed file and mark it as non-orphaned. */ 2914 PRTFSISOMAKERFILE pFile; 2915 rc = rtFsIsoMakerAddUnnamedFileWorker(pThis, NULL, 0, &pFile); 2916 if (RT_SUCCESS(rc)) 2917 { 2918 pFile->enmSrcType = RTFSISOMAKERSRCTYPE_VFS_FILE; 2919 pFile->u.hVfsFile = hVfsFile; 2920 pFile->pBootInfoTable = NULL; 2921 pFile->Core.fNotOrphan = true; 2922 2923 /* Save file pointer and we're done. */ 2924 pThis->pBootCatFile = pFile; 2925 return VINF_SUCCESS; 2926 } 2927 RTVfsFileRelease(hVfsFile); 2928 } 2929 return rc; 2930 } 2931 2932 2933 /** 2934 * Queries the configuration index of the boot catalog file object. 2935 * 2936 * The boot catalog file is created as necessary, thus this have to be a query 2937 * rather than a getter since object creation may fail. 2938 * 2939 * @returns IPRT status code. 2940 * @param hIsoMaker The ISO maker handle. 2941 * @param pidxObj Where to return the configuration index. 2942 */ 2943 RTDECL(int) RTFsIsoMakerQueryObjIdxForBootCatalog(RTFSISOMAKER hIsoMaker, uint32_t *pidxObj) 2944 { 2945 /* 2946 * Validate input. 2947 */ 2948 AssertPtrReturn(pidxObj, VERR_INVALID_POINTER); 2949 *pidxObj = UINT32_MAX; 2950 PRTFSISOMAKERINT pThis = hIsoMaker; 2951 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 2952 2953 /* 2954 * Do the job. 2955 */ 2956 int rc = rtFsIsoMakerEnsureBootCatFile(pThis); 2957 if (RT_SUCCESS(rc)) 2958 *pidxObj = pThis->pBootCatFile->Core.idxObj; 2959 return rc; 2960 } 2779 2961 2780 2962 … … 3010 3192 /* Set the translation table file size. */ 3011 3193 if (pCurDir->pTransTblFile) 3194 { 3012 3195 pCurDir->pTransTblFile->cbData = cbTransTbl; 3196 pThis->cbData += RT_ALIGN_32(cbTransTbl, RTFSISOMAKER_SECTOR_SIZE); 3197 } 3013 3198 3014 3199 /* Add to the path table size calculation. */ … … 3108 3293 *poffData += RT_ALIGN_64(pCurFile->cbData, RTFSISOMAKER_SECTOR_SIZE); 3109 3294 RTListAppend(&pThis->FinalizedFiles, &pCurFile->FinalizedEntry); 3295 } 3296 3297 /* 3298 * Create the boot info table. 3299 */ 3300 if (pCurFile->pBootInfoTable) 3301 { 3302 /* 3303 * Checksum the file. 3304 */ 3305 int rc; 3306 RTVFSFILE hVfsFile; 3307 switch (pCurFile->enmSrcType) 3308 { 3309 case RTFSISOMAKERSRCTYPE_PATH: 3310 rc = RTVfsChainOpenFile(pCurFile->u.pszSrcPath, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, 3311 &hVfsFile, NULL, NULL); 3312 AssertMsgRCReturn(rc, ("%s -> %Rrc\n", pCurFile->u.pszSrcPath, rc), rc); 3313 break; 3314 case RTFSISOMAKERSRCTYPE_VFS_FILE: 3315 hVfsFile = pCurFile->u.hVfsFile; 3316 rc = VINF_SUCCESS; 3317 break; 3318 default: 3319 AssertMsgFailedReturn(("enmSrcType=%d\n", pCurFile->enmSrcType), VERR_INTERNAL_ERROR_3); 3320 } 3321 3322 uint32_t uChecksum = 0; 3323 uint32_t off = 64; 3324 uint32_t cbLeft = RT_MAX(64, (uint32_t)pCurFile->cbData) - 64; 3325 while (cbLeft > 0) 3326 { 3327 union 3328 { 3329 uint8_t ab[_16K]; 3330 uint32_t au32[_16K / sizeof(uint32_t)]; 3331 } uBuf; 3332 uint32_t cbRead = RT_MIN(sizeof(uBuf), cbLeft); 3333 if (cbRead & 3) 3334 RT_ZERO(uBuf); 3335 rc = RTVfsFileReadAt(hVfsFile, off, &uBuf, cbRead, NULL); 3336 if (RT_FAILURE(rc)) 3337 break; 3338 3339 size_t i = RT_ALIGN_Z(cbRead, sizeof(uint32_t)) / sizeof(uint32_t); 3340 while (i-- > 0) 3341 uChecksum += RT_LE2H_U32(uBuf.au32[i]); 3342 3343 off += cbRead; 3344 cbLeft -= cbRead; 3345 } 3346 3347 if (pCurFile->enmSrcType == RTFSISOMAKERSRCTYPE_PATH) 3348 RTVfsFileRelease(hVfsFile); 3349 if (RT_FAILURE(rc)) 3350 return rc; 3351 3352 /* 3353 * Populate the structure. 3354 */ 3355 pCurFile->pBootInfoTable->offPrimaryVolDesc = RT_H2LE_U32(16 * RTFSISOMAKER_SECTOR_SIZE); 3356 pCurFile->pBootInfoTable->offBootFile = RT_H2LE_U32((uint32_t)(pCurFile->offData / RTFSISOMAKER_SECTOR_SIZE)); 3357 pCurFile->pBootInfoTable->cbBootFile = RT_H2LE_U32((uint32_t)pCurFile->cbData); 3358 pCurFile->pBootInfoTable->uChecksum = RT_H2LE_U32(uChecksum); 3359 RT_ZERO(pCurFile->pBootInfoTable->auReserved); 3110 3360 } 3111 3361 } … … 3491 3741 { 3492 3742 PRTFSISOMAKERINT pThis = hIsoMaker; 3493 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);3743 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 3494 3744 AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER); 3495 3745 … … 3791 4041 return rc; 3792 4042 *pcbDone = cbToRead; 4043 4044 /* 4045 * Do boot info table patching. 4046 */ 4047 if ( pFile->pBootInfoTable 4048 && offInFile < 64 4049 && offInFile + cbToRead > 8) 4050 { 4051 size_t offInBuf = offInFile < 8 ? 8 - (size_t)offInFile : 0; 4052 size_t offInTab = offInFile <= 8 ? 0 : (size_t)offInFile - 8; 4053 size_t cbToCopy = RT_MIN(sizeof(*pFile->pBootInfoTable) - offInTab, cbToRead - offInBuf); 4054 memcpy(&pbBuf[offInBuf], (uint8_t *)pFile->pBootInfoTable + offInTab, cbToCopy); 4055 } 3793 4056 3794 4057 /* … … 4645 4908 { 4646 4909 PRTFSISOMAKERINT pThis = hIsoMaker; 4647 RTFSISOMAKER_ASSER _VALID_HANDLE_RET(pThis);4910 RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis); 4648 4911 AssertReturn(pThis->fFinalized, VERR_WRONG_ORDER); 4649 4912 AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER); -
trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp
r67434 r67437 268 268 * pszImageNameInIso is used (i.e. -b option) and we've delayed everything 269 269 * boot related till after all files have been added to the image. */ 270 uint32_t id Image;270 uint32_t idxImageObj; 271 271 /** Whether to insert boot info table into the image. */ 272 272 bool fInsertBootInfoTable; 273 273 /** Bootble or not. Possible to make BIOS set up emulation w/o booting it. */ 274 274 bool fBootable; 275 /** The media type (ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX) and flags 276 * (ISO9660_ELTORITO_BOOT_MEDIA_F_XXX). */ 275 /** The media type (ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX). */ 277 276 uint8_t bBootMediaType; 278 277 /** File system / partition type. */ … … 332 331 /** Number of boot catalog entries (aBootCatEntries). */ 333 332 uint32_t cBootCatEntries; 334 /** Number of boot catalog entries we're done with (i.e. added to hIsoMaker). */335 uint32_t cBootCatEntriesDone;336 333 /** Boot catalog entries. */ 337 334 RTFSISOMKCMDELTORITOENTRY aBootCatEntries[64]; … … 346 343 347 344 /** 348 * Parsed name.349 */ 350 typedef struct RTFSISOM AKERCMDPARSEDNAME345 * One parsed name. 346 */ 347 typedef struct RTFSISOMKCMDPARSEDNAME 351 348 { 352 349 /** Copy of the corresponding RTFSISOMAKERCMDOPTS::afNameSpecifiers … … 357 354 /** Specified path. */ 358 355 char szPath[RTPATH_MAX]; 359 } RTFSISOM AKERCMDPARSEDNAME;356 } RTFSISOMKCMDPARSEDNAME; 360 357 /** Pointer to a parsed name. */ 361 typedef RTFSISOM AKERCMDPARSEDNAME *PRTFSISOMAKERCMDPARSEDNAME;358 typedef RTFSISOMKCMDPARSEDNAME *PRTFSISOMKCMDPARSEDNAME; 362 359 /** Pointer to a const parsed name. */ 363 typedef RTFSISOMAKERCMDPARSEDNAME const *PCRTFSISOMAKERCMDPARSEDNAME; 360 typedef RTFSISOMKCMDPARSEDNAME const *PCRTFSISOMKCMDPARSEDNAME; 361 362 363 /** 364 * Parsed names. 365 */ 366 typedef struct RTFSISOMKCMDPARSEDNAMES 367 { 368 /** Number of names. */ 369 uint32_t cNames; 370 /** Number of names with the source. */ 371 uint32_t cNamesWithSrc; 372 /** Special source types. 373 * Used for conveying commands to do on names intead of adding a source. 374 * Only used when adding generic stuff w/o any options involved. */ 375 enum 376 { 377 kSrcType_None, 378 kSrcType_Normal, 379 kSrcType_Remove, 380 kSrcType_MustRemove 381 } enmSrcType; 382 /** The parsed names. */ 383 RTFSISOMKCMDPARSEDNAME aNames[RTFSISOMAKERCMD_MAX_NAMES + 1]; 384 } RTFSISOMKCMDPARSEDNAMES; 385 /** Pointer to parsed names. */ 386 typedef RTFSISOMKCMDPARSEDNAMES *PRTFSISOMKCMDPARSEDNAMES; 387 /** Pointer to const parsed names. */ 388 typedef RTFSISOMKCMDPARSEDNAMES *PCRTFSISOMKCMDPARSEDNAMES; 389 364 390 365 391 … … 1037 1063 1038 1064 /** 1039 * Adds a file.1065 * Processes a non-option argument. 1040 1066 * 1041 1067 * @returns IPRT status code. 1042 1068 * @param pOpts The ISO maker command instance. 1043 * @param pszSrc The path to the source file.1044 * @param paParsedNames Array of parsed names, there are1045 * pOpts->cNameSpecifiers entries in the array.1046 */1047 static int rtFsIsoMakerCmdAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMAKERCMDPARSEDNAME paParsedNames)1048 {1049 uint32_t idxObj;1050 int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj);1051 if (RT_SUCCESS(rc))1052 {1053 pOpts->cItemsAdded++;1054 1055 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)1056 if (paParsedNames[i].cchPath > 0)1057 {1058 if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)1059 {1060 rc = RTFsIsoMakerObjSetPath(pOpts->hIsoMaker, idxObj,1061 paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,1062 paParsedNames[i].szPath);1063 if (RT_FAILURE(rc))1064 {1065 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting name '%s' on '%s': %Rrc",1066 paParsedNames[i].szPath, pszSrc, rc);1067 break;1068 }1069 }1070 if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK)1071 {1072 /** @todo add APIs for this. */1073 }1074 }1075 }1076 else1077 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc);1078 return rc;1079 }1080 1081 1082 /**1083 * Processes a non-option argument.1084 *1085 * @returns IPRT status code.1086 * @param pOpts The ISO maker command instance.1087 1069 * @param pszSpec The specification of what to add. 1088 */ 1089 static int rtFsIsoMakerCmdAddSomething(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec) 1090 { 1091 const char * const pszSpecIn = pszSpec; 1092 enum { kSpecialSrc_Normal, kSpecialSrc_Remove, kSpecialSrc_MustRemove } enmSpecialSrc = kSpecialSrc_Normal; 1070 * @param fWithSrc Whether the specification includes a source path 1071 * or not. 1072 * @param pParsed Where to return the parsed name specification. 1073 */ 1074 static int rtFsIsoMakerCmdParseNameSpec(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec, bool fWithSrc, 1075 PRTFSISOMKCMDPARSEDNAMES pParsed) 1076 { 1077 const char * const pszSpecIn = pszSpec; 1078 uint32_t const cMaxNames = pOpts->cNameSpecifiers + fWithSrc; 1093 1079 1094 1080 /* 1095 * Split it up by '='. Because of the source, which comes last,1081 * Split it up by '='. 1096 1082 */ 1097 RTFSISOMAKERCMDPARSEDNAME aParsedNames[RTFSISOMAKERCMD_MAX_NAMES + 1]; 1098 uint32_t cParsedNames = 0; 1083 pParsed->cNames = 0; 1084 pParsed->cNamesWithSrc = 0; 1085 pParsed->enmSrcType = fWithSrc ? RTFSISOMKCMDPARSEDNAMES::kSrcType_Normal : RTFSISOMKCMDPARSEDNAMES::kSrcType_None; 1099 1086 for (;;) 1100 1087 { 1101 1088 const char *pszEqual = strchr(pszSpec, '='); 1102 1089 size_t cchName = pszEqual ? pszEqual - pszSpec : strlen(pszSpec); 1103 bool fNeedSlash = pszEqual&& !RTPATH_IS_SLASH(*pszSpec) && cchName > 0;1104 if (cchName + fNeedSlash >= sizeof( aParsedNames[cParsedNames].szPath))1105 return rtFsIsoMakerCmdSyntaxError(pOpts, "name #%u (0-based) is too long: %s", cParsedNames, pszSpecIn);1106 if ( cParsedNames >= pOpts->cNameSpecifiers + 1)1107 return rtFsIsoMakerCmdSyntaxError(pOpts, "too many names specified (max %u + source): %s",1108 pOpts->cNameSpecifiers, pszSpecIn);1090 bool fNeedSlash = (pszEqual || !fWithSrc) && !RTPATH_IS_SLASH(*pszSpec) && cchName > 0; 1091 if (cchName + fNeedSlash >= sizeof(pParsed->aNames[pParsed->cNamesWithSrc].szPath)) 1092 return rtFsIsoMakerCmdSyntaxError(pOpts, "name #%u (0-based) is too long: %s", pParsed->cNamesWithSrc, pszSpecIn); 1093 if (pParsed->cNamesWithSrc >= cMaxNames) 1094 return rtFsIsoMakerCmdSyntaxError(pOpts, "too many names specified (max %u%s): %s", 1095 pOpts->cNameSpecifiers, fWithSrc ? " + source" : "", pszSpecIn); 1109 1096 if (!fNeedSlash) 1110 memcpy( aParsedNames[cParsedNames].szPath, pszSpec, cchName);1097 memcpy(pParsed->aNames[pParsed->cNamesWithSrc].szPath, pszSpec, cchName); 1111 1098 else 1112 1099 { 1113 memcpy(& aParsedNames[cParsedNames].szPath[1], pszSpec, cchName);1114 aParsedNames[cParsedNames].szPath[0] = RTPATH_SLASH;1100 memcpy(&pParsed->aNames[pParsed->cNamesWithSrc].szPath[1], pszSpec, cchName); 1101 pParsed->aNames[pParsed->cNamesWithSrc].szPath[0] = RTPATH_SLASH; 1115 1102 cchName++; 1116 1103 } 1117 aParsedNames[cParsedNames].szPath[cchName] = '\0';1118 aParsedNames[cParsedNames].cchPath = (uint32_t)cchName;1119 cParsedNames++;1120 1121 if (!pszEqual )1104 pParsed->aNames[pParsed->cNamesWithSrc].szPath[cchName] = '\0'; 1105 pParsed->aNames[pParsed->cNamesWithSrc].cchPath = (uint32_t)cchName; 1106 pParsed->cNamesWithSrc++; 1107 1108 if (!pszEqual && fWithSrc) 1122 1109 { 1123 1110 if (!cchName) 1124 1111 return rtFsIsoMakerCmdSyntaxError(pOpts, "empty source file name: %s", pszSpecIn); 1125 1112 if (cchName == 8 && strcmp(pszSpec, ":remove:") == 0) 1126 enmSpecialSrc = kSpecialSrc_Remove;1113 pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove; 1127 1114 else if (cchName == 13 && strcmp(pszSpec, ":must-remove:") == 0) 1128 enmSpecialSrc = kSpecialSrc_MustRemove;1115 pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove; 1129 1116 break; 1130 1117 } … … 1133 1120 1134 1121 /* 1135 * If there are too few names specified, move the source and repeat the penultimate name. 1122 * If there are too few names specified, move the source and repeat the 1123 * last non-source name. If only source, convert source into a name spec. 1136 1124 */ 1137 if (cParsedNames < pOpts->cNameSpecifiers + 1) 1138 { 1139 aParsedNames[pOpts->cNameSpecifiers] = aParsedNames[cParsedNames - 1]; 1140 uint32_t iSrc = cParsedNames >= 2 ? cParsedNames - 2 : 0; 1125 if (pParsed->cNamesWithSrc < cMaxNames) 1126 { 1127 uint32_t iSrc; 1128 if (!fWithSrc) 1129 iSrc = pParsed->cNamesWithSrc - 1; 1130 else 1131 { 1132 pParsed->aNames[pOpts->cNameSpecifiers] = pParsed->aNames[pParsed->cNamesWithSrc - 1]; 1133 iSrc = pParsed->cNamesWithSrc >= 2 ? pParsed->cNamesWithSrc - 2 : 0; 1134 } 1141 1135 1142 1136 /* If the source is a input file name specifier, reduce it to something that starts with a slash. */ 1143 if ( cParsedNames == 1)1137 if (pParsed->cNamesWithSrc == 1 && fWithSrc) 1144 1138 { 1145 if (RTVfsChainIsSpec( aParsedNames[iSrc].szPath))1139 if (RTVfsChainIsSpec(pParsed->aNames[iSrc].szPath)) 1146 1140 { 1147 1141 uint32_t offError; 1148 1142 char *pszFinalPath; 1149 int rc = RTVfsChainQueryFinalPath( aParsedNames[iSrc].szPath, &pszFinalPath, &offError);1143 int rc = RTVfsChainQueryFinalPath(pParsed->aNames[iSrc].szPath, &pszFinalPath, &offError); 1150 1144 if (RT_FAILURE(rc)) 1151 1145 return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryFinalPath", 1152 aParsedNames[iSrc].szPath, rc, offError, NULL);1153 aParsedNames[iSrc].cchPath = (uint32_t)strlen(pszFinalPath);1146 pParsed->aNames[iSrc].szPath, rc, offError, NULL); 1147 pParsed->aNames[iSrc].cchPath = (uint32_t)strlen(pszFinalPath); 1154 1148 if (RTPATH_IS_SLASH(*pszFinalPath)) 1155 memcpy( aParsedNames[iSrc].szPath, pszFinalPath, aParsedNames[iSrc].cchPath + 1);1149 memcpy(pParsed->aNames[iSrc].szPath, pszFinalPath, pParsed->aNames[iSrc].cchPath + 1); 1156 1150 else 1157 1151 { 1158 memcpy(& aParsedNames[iSrc].szPath[1], pszFinalPath, aParsedNames[iSrc].cchPath + 1);1159 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;1160 aParsedNames[iSrc].cchPath++;1152 memcpy(&pParsed->aNames[iSrc].szPath[1], pszFinalPath, pParsed->aNames[iSrc].cchPath + 1); 1153 pParsed->aNames[iSrc].szPath[0] = RTPATH_SLASH; 1154 pParsed->aNames[iSrc].cchPath++; 1161 1155 } 1162 1156 RTStrFree(pszFinalPath); 1163 1157 } 1164 1158 #if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS 1165 else if ( RTPATH_IS_VOLSEP( aParsedNames[iSrc].szPath[1])1166 && RT_C_IS_ALPHA( aParsedNames[iSrc].szPath[0]))1159 else if ( RTPATH_IS_VOLSEP(pParsed->aNames[iSrc].szPath[1]) 1160 && RT_C_IS_ALPHA(pParsed->aNames[iSrc].szPath[0])) 1167 1161 { 1168 if (RTPATH_IS_SLASH( aParsedNames[iSrc].szPath[2]))1162 if (RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[2])) 1169 1163 { 1170 memmove(& aParsedNames[iSrc].szPath[0], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1);1171 aParsedNames[iSrc].cchPath -= 2;1164 memmove(&pParsed->aNames[iSrc].szPath[0], &pParsed->aNames[iSrc].szPath[2], pParsed->aNames[iSrc].cchPath - 1); 1165 pParsed->aNames[iSrc].cchPath -= 2; 1172 1166 } 1173 1167 else 1174 1168 { 1175 memmove(& aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1);1176 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;1177 aParsedNames[iSrc].cchPath -= 1;1169 memmove(&pParsed->aNames[iSrc].szPath[1], &pParsed->aNames[iSrc].szPath[2], pParsed->aNames[iSrc].cchPath - 1); 1170 pParsed->aNames[iSrc].szPath[0] = RTPATH_SLASH; 1171 pParsed->aNames[iSrc].cchPath -= 1; 1178 1172 } 1179 1173 } 1180 1174 #endif 1181 else if (!RTPATH_IS_SLASH( aParsedNames[iSrc].szPath[0]))1175 else if (!RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[0])) 1182 1176 { 1183 if ( aParsedNames[iSrc].cchPath + 2 > sizeof(aParsedNames[iSrc].szPath))1177 if (pParsed->aNames[iSrc].cchPath + 2 > sizeof(pParsed->aNames[iSrc].szPath)) 1184 1178 return rtFsIsoMakerCmdSyntaxError(pOpts, "name too long: %s", pszSpecIn); 1185 memmove(& aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[0], aParsedNames[iSrc].cchPath + 1);1186 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;1187 aParsedNames[iSrc].cchPath++;1179 memmove(&pParsed->aNames[iSrc].szPath[1], &pParsed->aNames[iSrc].szPath[0], pParsed->aNames[iSrc].cchPath + 1); 1180 pParsed->aNames[iSrc].szPath[0] = RTPATH_SLASH; 1181 pParsed->aNames[iSrc].cchPath++; 1188 1182 } 1189 1183 } 1190 1184 1191 1185 for (uint32_t iDst = iSrc + 1; iDst < pOpts->cNameSpecifiers; iDst++) 1192 aParsedNames[iDst] = aParsedNames[iSrc]; 1193 cParsedNames = pOpts->cNameSpecifiers + 1; 1194 } 1186 pParsed->aNames[iDst] = pParsed->aNames[iSrc]; 1187 1188 pParsed->cNamesWithSrc = cMaxNames; 1189 } 1190 pParsed->cNames = pOpts->cNameSpecifiers; 1195 1191 1196 1192 /* … … 1199 1195 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 1200 1196 { 1201 aParsedNames[i].fNameSpecifiers = pOpts->afNameSpecifiers[i]; 1202 Assert( aParsedNames[i].cchPath == 0 1203 || RTPATH_IS_SLASH(aParsedNames[i].szPath[0])); 1204 } 1197 pParsed->aNames[i].fNameSpecifiers = pOpts->afNameSpecifiers[i]; 1198 Assert( pParsed->aNames[i].cchPath == 0 1199 || RTPATH_IS_SLASH(pParsed->aNames[i].szPath[0])); 1200 } 1201 1202 return VINF_SUCCESS; 1203 } 1204 1205 1206 /** 1207 * Enteres an object into the namespace by full paths. 1208 * 1209 * This is used by rtFsIsoMakerCmdOptEltoritoSetBootCatalogPath and 1210 * rtFsIsoMakerCmdAddFile. 1211 * 1212 * @returns IPRT status code. 1213 * @param pOpts The ISO maker command instance. 1214 * @param idxObj The configuration index of the object to be named. 1215 * @param pParsed The parsed names. 1216 * @param pszSrcOrName Source file or name. 1217 */ 1218 static int rtFsIsoMakerCmdSetObjPaths(PRTFSISOMAKERCMDOPTS pOpts, uint32_t idxObj, PCRTFSISOMKCMDPARSEDNAMES pParsed, 1219 const char *pszSrcOrName) 1220 { 1221 int rc = VINF_SUCCESS; 1222 for (uint32_t i = 0; i < pParsed->cNames; i++) 1223 if (pParsed->aNames[i].cchPath > 0) 1224 { 1225 if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK) 1226 { 1227 rc = RTFsIsoMakerObjSetPath(pOpts->hIsoMaker, idxObj, 1228 pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK, 1229 pParsed->aNames[i].szPath); 1230 if (RT_FAILURE(rc)) 1231 { 1232 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting name '%s' on '%s': %Rrc", 1233 pParsed->aNames[i].szPath, pszSrcOrName, rc); 1234 break; 1235 } 1236 } 1237 if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK) 1238 { 1239 /** @todo add APIs for this. */ 1240 } 1241 } 1242 return rc; 1243 } 1244 1245 1246 /** 1247 * Adds a file. 1248 * 1249 * @returns IPRT status code. 1250 * @param pOpts The ISO maker command instance. 1251 * @param pszSrc The path to the source file. 1252 * @param pParsed The parsed names. 1253 * @param pidxObj Where to return the configuration index for the 1254 * added file. Optional. 1255 */ 1256 static int rtFsIsoMakerCmdAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMKCMDPARSEDNAMES pParsed, 1257 uint32_t *pidxObj) 1258 { 1259 uint32_t idxObj; 1260 int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj); 1261 if (RT_SUCCESS(rc)) 1262 { 1263 pOpts->cItemsAdded++; 1264 if (pidxObj) 1265 *pidxObj = idxObj; 1266 1267 rc = rtFsIsoMakerCmdSetObjPaths(pOpts, idxObj, pParsed, pszSrc); 1268 } 1269 else 1270 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc); 1271 return rc; 1272 } 1273 1274 1275 /** 1276 * Adds a file after first making sure it's a file. 1277 * 1278 * @returns IPRT status code 1279 * @param pOpts The ISO maker command instance. 1280 * @param pszSrc The path to the source file. 1281 * @param pParsed The parsed names. 1282 * @param pidxObj Where to return the configuration index for the 1283 * added file. Optional. 1284 */ 1285 static int rtFsIsoMakerCmdStatAndAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMKCMDPARSEDNAMES pParsed, 1286 uint32_t *pidxObj) 1287 { 1288 RTFSOBJINFO ObjInfo; 1289 uint32_t offError; 1290 RTERRINFOSTATIC ErrInfo; 1291 int rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX, 1292 RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo)); 1293 if (RT_FAILURE(rc)) 1294 return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryInfo", pszSrc, rc, offError, &ErrInfo.Core); 1295 1296 if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) 1297 return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, pParsed, pidxObj); 1298 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_A_FILE, "Not a file: %s", pszSrc); 1299 } 1300 1301 1302 /** 1303 * Processes a non-option argument. 1304 * 1305 * @returns IPRT status code. 1306 * @param pOpts The ISO maker command instance. 1307 * @param pszSpec The specification of what to add. 1308 */ 1309 static int rtFsIsoMakerCmdAddSomething(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec) 1310 { 1311 /* 1312 * Parse the name spec. 1313 */ 1314 RTFSISOMKCMDPARSEDNAMES Parsed; 1315 int rc = rtFsIsoMakerCmdParseNameSpec(pOpts, pszSpec, true /*fWithSrc*/, &Parsed); 1316 if (RT_FAILURE(rc)) 1317 return rc; 1205 1318 1206 1319 /* 1207 1320 * Deal with special source filenames used to remove/change stuff. 1208 1321 */ 1209 if ( enmSpecialSrc == kSpecialSrc_Remove1210 || enmSpecialSrc == kSpecialSrc_MustRemove)1322 if ( Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove 1323 || Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove) 1211 1324 { 1212 1325 const char *pszFirstNm = NULL; 1213 1326 uint32_t cRemoved = 0; 1214 1327 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 1215 if ( aParsedNames[i].cchPath > 01216 && ( aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))1328 if ( Parsed.aNames[i].cchPath > 0 1329 && (Parsed.aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)) 1217 1330 { 1218 pszFirstNm = aParsedNames[i].szPath;1331 pszFirstNm = Parsed.aNames[i].szPath; 1219 1332 uint32_t idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, 1220 aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,1221 aParsedNames[i].szPath);1333 Parsed.aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK, 1334 Parsed.aNames[i].szPath); 1222 1335 if (idxObj != UINT32_MAX) 1223 1336 { 1224 1337 int rc = RTFsIsoMakerObjRemove(pOpts->hIsoMaker, idxObj); 1225 1338 if (RT_FAILURE(rc)) 1226 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpec In, rc);1339 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpec, rc); 1227 1340 cRemoved++; 1228 1341 } 1229 1342 } 1230 if ( enmSpecialSrc == kSpecialSrc_MustRemove1343 if ( Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove 1231 1344 && cRemoved == 0) 1232 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpec In);1345 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpec); 1233 1346 } 1234 1347 /* … … 1237 1350 else 1238 1351 { 1239 const char *pszSrc = aParsedNames[cParsedNames- 1].szPath;1352 const char *pszSrc = Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath; 1240 1353 RTFSOBJINFO ObjInfo; 1241 1354 uint32_t offError; … … 1247 1360 1248 1361 if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) 1249 return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, aParsedNames); 1362 return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, &Parsed, NULL /*pidxObj*/); 1363 1250 1364 if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) 1251 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpecIn); 1365 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpec); 1366 1252 1367 if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)) 1253 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpecIn); 1254 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpecIn); 1368 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpec); 1369 1370 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpec); 1255 1371 } 1256 1372 … … 1295 1411 1296 1412 /** 1297 * Deals with: --boot-catalog <path-spec> 1298 * 1299 * This enters the boot catalog into the namespaces of the image. The path-spec 1300 * is similar to what rtFsIsoMakerCmdAddSomething processes, only there isn't a 1301 * source file part. 1413 * Helper that makes sure we've got a validation boot entry. 1302 1414 * 1303 1415 * @returns IPRT status code 1304 1416 * @param pOpts The ISO maker command instance. 1305 * @param pszGenericBootImage The generic boot image source. 1306 */ 1307 static int rtFsIsoMakerCmdOptEltoritoSetBootCatalogPath(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootCat) 1308 { 1309 RT_NOREF(pOpts, pszBootCat); 1310 return VERR_NOT_IMPLEMENTED; 1311 } 1312 1313 1314 /** 1315 * Helper that makes sure we've got a validation boot entry. 1316 * 1317 * @returns IPRT status code 1318 * @param pOpts The ISO maker command instance. 1319 */ 1320 static void rtFsIsoMakerCmdOptEltoritoEnsureValiidationEntry(PRTFSISOMAKERCMDOPTS pOpts) 1417 */ 1418 static void rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(PRTFSISOMAKERCMDOPTS pOpts) 1321 1419 { 1322 1420 if (pOpts->cBootCatEntries == 0) … … 1340 1438 static int rtFsIsoMakerCmdOptEltoritoEnsureSectionEntry(PRTFSISOMAKERCMDOPTS pOpts, bool fForceNew, uint32_t *pidxBootCat) 1341 1439 { 1342 rtFsIsoMakerCmdOptEltoritoEnsureVali idationEntry(pOpts);1440 rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts); 1343 1441 1344 1442 uint32_t i = pOpts->cBootCatEntries; … … 1364 1462 : RTFSISOMKCMDELTORITOENTRY::kEntryType_Section; 1365 1463 pOpts->aBootCatEntries[i].u.Section.pszImageNameInIso = NULL; 1366 pOpts->aBootCatEntries[i].u.Section.id Image= UINT32_MAX;1464 pOpts->aBootCatEntries[i].u.Section.idxImageObj = UINT32_MAX; 1367 1465 pOpts->aBootCatEntries[i].u.Section.fInsertBootInfoTable = false; 1368 1466 pOpts->aBootCatEntries[i].u.Section.fBootable = true; … … 1380 1478 1381 1479 /** 1480 * Deals with: --boot-catalog <path-spec> 1481 * 1482 * This enters the boot catalog into the namespaces of the image. The path-spec 1483 * is similar to what rtFsIsoMakerCmdAddSomething processes, only there isn't a 1484 * source file part. 1485 * 1486 * @returns IPRT status code 1487 * @param pOpts The ISO maker command instance. 1488 * @param pszGenericBootImage The generic boot image source. 1489 */ 1490 static int rtFsIsoMakerCmdOptEltoritoSetBootCatalogPath(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootCat) 1491 { 1492 /* Make sure we'll fail later if no other boot options are present. */ 1493 rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts); 1494 1495 /* Parse the name spec. */ 1496 RTFSISOMKCMDPARSEDNAMES Parsed; 1497 int rc = rtFsIsoMakerCmdParseNameSpec(pOpts, pszBootCat, false /*fWithSrc*/, &Parsed); 1498 if (RT_SUCCESS(rc)) 1499 { 1500 /* Query/create the boot catalog and enter it into the name spaces. */ 1501 uint32_t idxBootCatObj; 1502 rc = RTFsIsoMakerQueryObjIdxForBootCatalog(pOpts->hIsoMaker, &idxBootCatObj); 1503 if (RT_SUCCESS(rc)) 1504 rc = rtFsIsoMakerCmdSetObjPaths(pOpts, idxBootCatObj, &Parsed, "boot catalog"); 1505 else 1506 rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTFsIsoMakerQueryBootCatalogPathObjIdx failed: %Rrc", rc); 1507 } 1508 return rc; 1509 } 1510 1511 1512 /** 1382 1513 * Deals with: --eltorito-add-image {file-spec} 1383 1514 * … … 1394 1525 static int rtFsIsoMakerCmdOptEltoritoAddImage(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootImageSpec) 1395 1526 { 1396 RT_NOREF(pOpts, pszBootImageSpec); 1397 return VERR_NOT_IMPLEMENTED; 1527 /* Parse the name spec. */ 1528 RTFSISOMKCMDPARSEDNAMES Parsed; 1529 int rc = rtFsIsoMakerCmdParseNameSpec(pOpts, pszBootImageSpec, true /*fWithSrc*/, &Parsed); 1530 if (RT_SUCCESS(rc)) 1531 { 1532 uint32_t idxBootCat; 1533 rc = rtFsIsoMakerCmdOptEltoritoEnsureSectionEntry(pOpts, false /*fForceNew*/, &idxBootCat); 1534 if (RT_SUCCESS(rc)) 1535 { 1536 if ( pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj != UINT32_MAX 1537 || pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso != NULL) 1538 rc = rtFsIsoMakerCmdSyntaxError(pOpts, "boot image already given for current El Torito entry (%#u)", idxBootCat); 1539 else 1540 { 1541 uint32_t idxImageObj; 1542 rc = rtFsIsoMakerCmdStatAndAddFile(pOpts, Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath, &Parsed, &idxImageObj); 1543 if (RT_SUCCESS(rc)) 1544 pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj; 1545 } 1546 } 1547 } 1548 1549 return rc; 1398 1550 } 1399 1551 … … 1414 1566 if (RT_SUCCESS(rc)) 1415 1567 { 1416 if ( pOpts->aBootCatEntries[idxBootCat].u.Section.id Image!= UINT32_MAX1568 if ( pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj != UINT32_MAX 1417 1569 || pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso != NULL) 1418 1570 return rtFsIsoMakerCmdSyntaxError(pOpts, "boot image already given for current El Torito entry (%#u)", idxBootCat); 1419 1571 1420 uint32_t idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, RTFSISOMAKER_NAMESPACE_ALL, pszBootImage); 1421 pOpts->aBootCatEntries[idxBootCat].u.Section.idImage = idxObj; 1422 if (idxObj == UINT32_MAX) 1572 uint32_t idxImageObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, RTFSISOMAKER_NAMESPACE_ALL, pszBootImage); 1573 if (idxImageObj == UINT32_MAX) 1423 1574 pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso = pszBootImage; 1575 pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj; 1424 1576 } 1425 1577 return rc; … … 1459 1611 if (pOpts->cBootCatEntries <= 1) 1460 1612 { 1461 rtFsIsoMakerCmdOptEltoritoEnsureVali idationEntry(pOpts);1613 rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts); 1462 1614 pOpts->aBootCatEntries[0].u.Validation.idPlatform = idPlatform; 1463 1615 } … … 1575 1727 pOpts->aBootCatEntries[idxBootCat].u.Section.fInsertBootInfoTable = true; 1576 1728 return rc; 1729 } 1730 1731 1732 /** 1733 * Validates and commits the boot catalog stuff. 1734 * 1735 * ASSUMING this is called after all options are parsed and there is only this 1736 * one call. 1737 * 1738 * @returns IPRT status code 1739 * @param pOpts The ISO maker command instance. 1740 */ 1741 static int rtFsIsoMakerCmdOptEltoritoCommitBootCatalog(PRTFSISOMAKERCMDOPTS pOpts) 1742 { 1743 if (pOpts->cBootCatEntries == 0) 1744 return VINF_SUCCESS; 1745 1746 /* 1747 * Locate and configure the boot images first. 1748 */ 1749 for (uint32_t idxBootCat = 1; idxBootCat < pOpts->cBootCatEntries; idxBootCat++) 1750 if ( pOpts->aBootCatEntries[idxBootCat].enmType == RTFSISOMKCMDELTORITOENTRY::kEntryType_Default 1751 || pOpts->aBootCatEntries[idxBootCat].enmType == RTFSISOMKCMDELTORITOENTRY::kEntryType_Section) 1752 { 1753 /* Make sure we've got a boot image. */ 1754 uint32_t idxImageObj = pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj; 1755 if (idxImageObj == UINT32_MAX) 1756 { 1757 const char *pszBootImage = pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso; 1758 if (pszBootImage == NULL) 1759 return rtFsIsoMakerCmdSyntaxError(pOpts, "No image name given for boot catalog entry #%u", idxBootCat); 1760 1761 idxImageObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, RTFSISOMAKER_NAMESPACE_ALL, pszBootImage); 1762 if (idxImageObj == UINT32_MAX) 1763 return rtFsIsoMakerCmdSyntaxError(pOpts, "Unable to locate image for boot catalog entry #%u: %s", 1764 idxBootCat, pszBootImage); 1765 pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj; 1766 } 1767 1768 /* Enable patching it? */ 1769 if (pOpts->aBootCatEntries[idxBootCat].u.Section.fInsertBootInfoTable) 1770 { 1771 int rc = RTFsIsoMakerObjEnableBootInfoTablePatching(pOpts->hIsoMaker, idxImageObj, true); 1772 if (RT_FAILURE(rc)) 1773 return rtFsIsoMakerCmdErrorRc(pOpts, rc, 1774 "RTFsIsoMakerObjEnableBootInfoTablePatching failed on entry #%u: %Rrc\n", 1775 idxBootCat, rc); 1776 } 1777 1778 /* Figure out the floppy type given the object size. */ 1779 if (pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType == ISO9660_ELTORITO_BOOT_MEDIA_TYPE_MASK) 1780 { 1781 uint64_t cbImage; 1782 int rc = RTFsIsoMakerObjQueryDataSize(pOpts->hIsoMaker, idxImageObj, &cbImage); 1783 if (RT_FAILURE(rc)) 1784 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTFsIsoMakerObjGetDataSize failed on entry #%u: %Rrc\n", 1785 idxBootCat, rc); 1786 if (cbImage == 1228800) 1787 pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_1_2_MB; 1788 else if (cbImage <= 1474560) 1789 pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_1_44_MB; 1790 else if (cbImage <= 2949120) 1791 pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_2_88_MB; 1792 else 1793 pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_HARD_DISK; 1794 } 1795 } 1796 1797 /* 1798 * Add the boot catalog entries. 1799 */ 1800 1801 1802 return VINF_SUCCESS; 1577 1803 } 1578 1804
Note:
See TracChangeset
for help on using the changeset viewer.