VirtualBox

Changeset 67437 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jun 16, 2017 1:14:39 PM (7 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code (booting related).

Location:
trunk/src/VBox/Runtime/common/fs
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/isomaker.cpp

    r67427 r67437  
    5555*********************************************************************************************************************************/
    5656/** 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) \
    5858    do { AssertPtrReturn(a_pThis, a_rcRet); \
    5959         AssertReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, a_rcRet); \
     
    6161
    6262/** 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)
    6464
    6565/** The sector size. */
     
    374374    } u;
    375375
     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
    376380    /** Entry in the list of finalized directories. */
    377381    RTLISTNODE              FinalizedEntry;
     
    446450    /** The default file mode mask. */
    447451    RTFMODE                 fDefaultDirMode;
     452
     453    /** @name Boot related stuff
     454     * @{ */
     455    /** The boot catalog file. */
     456    PRTFSISOMAKERFILE       pBootCatFile;
     457
     458    /** @} */
    448459
    449460    /** @name Finalized image stuff
     
    728739        pThis->fDefaultDirMode              = 0555 | RTFS_TYPE_DIRECTORY | RTFS_DOS_DIRECTORY | RTFS_DOS_READONLY;
    729740
     741        //pThis->pBootCatFile               = NULL;
     742
    730743        pThis->cbFinalizedImage             = UINT64_MAX;
    731744        //pThis->pbSysArea                  = NULL;
     
    807820
    808821            /* no default, want warnings */
     822        }
     823        if (pFile->pBootInfoTable)
     824        {
     825            RTMemFree(pFile->pBootInfoTable);
     826            pFile->pBootInfoTable = NULL;
    809827        }
    810828    }
     
    10271045{
    10281046    PRTFSISOMAKERINT pThis = hIsoMaker;
    1029     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     1047    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    10301048    AssertReturn(uIsoLevel <= 3, VERR_INVALID_PARAMETER);
    10311049    AssertReturn(uIsoLevel > 0, VERR_INVALID_PARAMETER); /* currently not possible to disable this */
     
    10481066{
    10491067    PRTFSISOMAKERINT pThis = hIsoMaker;
    1050     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     1068    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    10511069    AssertReturn(uJolietLevel <= 3, VERR_INVALID_PARAMETER);
    10521070    AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
     
    10751093{
    10761094    PRTFSISOMAKERINT pThis = hIsoMaker;
    1077     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     1095    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    10781096    AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
    10791097    AssertReturn(uLevel <= 2, VERR_INVALID_PARAMETER);
     
    10951113{
    10961114    PRTFSISOMAKERINT pThis = hIsoMaker;
    1097     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     1115    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    10981116    AssertReturn(!pThis->fSeenContent, VERR_WRONG_ORDER);
    10991117    AssertReturn(uLevel <= 2, VERR_INVALID_PARAMETER);
     
    11241142     */
    11251143    PRTFSISOMAKERINT pThis = hIsoMaker;
    1126     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     1144    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    11271145    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    11281146    AssertReturn(cbContent > 0, VERR_OUT_OF_RANGE);
     
    17231741        pFile->enmSrcType     = RTFSISOMAKERSRCTYPE_TRANS_TBL;
    17241742        pFile->u.pTransTblDir = pDirName;
     1743        pFile->pBootInfoTable = NULL;
    17251744        pDirName->pDir->pTransTblFile = pFile;
    17261745
     
    22452264     */
    22462265    PRTFSISOMAKERINT pThis = hIsoMaker;
    2247     RTFSISOMAKER_ASSER_VALID_HANDLE_RET_EX(pThis, UINT32_MAX);
     2266    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET_EX(pThis, UINT32_MAX);
    22482267
    22492268    /*
     
    23232342     */
    23242343    PRTFSISOMAKERINT pThis = hIsoMaker;
    2325     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2344    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    23262345    PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj);
    23272346    AssertReturn(pObj, VERR_OUT_OF_RANGE);
     
    23562375     */
    23572376    PRTFSISOMAKERINT pThis = hIsoMaker;
    2358     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2377    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    23592378    AssertReturn(!(fNamespaces & ~RTFSISOMAKER_NAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
    23602379    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     
    24052424     */
    24062425    PRTFSISOMAKERINT pThis = hIsoMaker;
    2407     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2426    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    24082427    AssertReturn(!(fNamespaces & ~RTFSISOMAKER_NAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
    24092428    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     
    24422461
    24432462/**
     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 */
     2470RTDECL(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 */
     2516RTDECL(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/**
    24442545 * Initalizes the common part of a file system object and links it into global
    24452546 * chain.
     
    25282629{
    25292630    PRTFSISOMAKERINT pThis = hIsoMaker;
    2530     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2631    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    25312632    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
    25322633    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
     
    25532654{
    25542655    PRTFSISOMAKERINT pThis = hIsoMaker;
    2555     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2656    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    25562657    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
    25572658    AssertReturn(RTPATH_IS_SLASH(*pszDir), VERR_INVALID_NAME);
     
    25792680 * @returns IPRT status code.
    25802681 * @param   pThis               The ISO make instance.
     2682 * @param   pObjInfo            Object information.  Optional.
    25812683 * @param   cbExtra             Extra space for additional data (e.g. source
    25822684 *                              path string copy).
     
    26222724{
    26232725    PRTFSISOMAKERINT pThis = hIsoMaker;
    2624     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2726    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    26252727    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
    26262728    *pidxObj = UINT32_MAX;
     
    26442746    if (RT_SUCCESS(rc))
    26452747    {
    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;
    26482751
    26492752        *pidxObj = pFile->Core.idxObj;
     
    26682771{
    26692772    PRTFSISOMAKERINT pThis = hIsoMaker;
    2670     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2773    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    26712774    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
    26722775    *pidxObj = UINT32_MAX;
     
    26932796    if (RT_SUCCESS(rc))
    26942797    {
    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;
    26972801
    26982802        *pidxObj = pFile->Core.idxObj;
     
    27202824{
    27212825    PRTFSISOMAKERINT pThis = hIsoMaker;
    2722     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2826    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    27232827    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
    27242828    AssertReturn(RTPATH_IS_SLASH(*pszFile), VERR_INVALID_NAME);
     
    27572861{
    27582862    PRTFSISOMAKERINT pThis = hIsoMaker;
    2759     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2863    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    27602864    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
    27612865    AssertReturn(RTPATH_IS_SLASH(*pszFile), VERR_INVALID_NAME);
     
    27772881}
    27782882
     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 */
     2901static 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 */
     2943RTDECL(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}
    27792961
    27802962
     
    30103192            /* Set the translation table file size. */
    30113193            if (pCurDir->pTransTblFile)
     3194            {
    30123195                pCurDir->pTransTblFile->cbData = cbTransTbl;
     3196                pThis->cbData += RT_ALIGN_32(cbTransTbl, RTFSISOMAKER_SECTOR_SIZE);
     3197            }
    30133198
    30143199            /* Add to the path table size calculation. */
     
    31083293                *poffData += RT_ALIGN_64(pCurFile->cbData, RTFSISOMAKER_SECTOR_SIZE);
    31093294                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);
    31103360            }
    31113361        }
     
    34913741{
    34923742    PRTFSISOMAKERINT pThis = hIsoMaker;
    3493     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     3743    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    34943744    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    34953745
     
    37914041            return rc;
    37924042        *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        }
    37934056
    37944057        /*
     
    46454908{
    46464909    PRTFSISOMAKERINT pThis = hIsoMaker;
    4647     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     4910    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
    46484911    AssertReturn(pThis->fFinalized, VERR_WRONG_ORDER);
    46494912    AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER);
  • trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp

    r67434 r67437  
    268268             * pszImageNameInIso is used (i.e. -b option) and we've delayed everything
    269269             * boot related till after all files have been added to the image. */
    270             uint32_t    idImage;
     270            uint32_t    idxImageObj;
    271271            /** Whether to insert boot info table into the image. */
    272272            bool        fInsertBootInfoTable;
    273273            /** Bootble or not.  Possible to make BIOS set up emulation w/o booting it. */
    274274            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). */
    277276            uint8_t     bBootMediaType;
    278277            /** File system / partition type. */
     
    332331    /** Number of boot catalog entries (aBootCatEntries). */
    333332    uint32_t                    cBootCatEntries;
    334     /** Number of boot catalog entries we're done with (i.e. added to hIsoMaker). */
    335     uint32_t                    cBootCatEntriesDone;
    336333    /** Boot catalog entries. */
    337334    RTFSISOMKCMDELTORITOENTRY   aBootCatEntries[64];
     
    346343
    347344/**
    348  * Parsed name.
    349  */
    350 typedef struct RTFSISOMAKERCMDPARSEDNAME
     345 * One parsed name.
     346 */
     347typedef struct RTFSISOMKCMDPARSEDNAME
    351348{
    352349    /** Copy of the corresponding RTFSISOMAKERCMDOPTS::afNameSpecifiers
     
    357354    /** Specified path. */
    358355    char                szPath[RTPATH_MAX];
    359 } RTFSISOMAKERCMDPARSEDNAME;
     356} RTFSISOMKCMDPARSEDNAME;
    360357/** Pointer to a parsed name. */
    361 typedef RTFSISOMAKERCMDPARSEDNAME *PRTFSISOMAKERCMDPARSEDNAME;
     358typedef RTFSISOMKCMDPARSEDNAME *PRTFSISOMKCMDPARSEDNAME;
    362359/** Pointer to a const parsed name. */
    363 typedef RTFSISOMAKERCMDPARSEDNAME const *PCRTFSISOMAKERCMDPARSEDNAME;
     360typedef RTFSISOMKCMDPARSEDNAME const *PCRTFSISOMKCMDPARSEDNAME;
     361
     362
     363/**
     364 * Parsed names.
     365 */
     366typedef 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. */
     386typedef RTFSISOMKCMDPARSEDNAMES *PRTFSISOMKCMDPARSEDNAMES;
     387/** Pointer to const parsed names. */
     388typedef RTFSISOMKCMDPARSEDNAMES *PCRTFSISOMKCMDPARSEDNAMES;
     389
    364390
    365391
     
    10371063
    10381064/**
    1039  * Adds a file.
     1065 * Processes a non-option argument.
    10401066 *
    10411067 * @returns IPRT status code.
    10421068 * @param   pOpts               The ISO maker command instance.
    1043  * @param   pszSrc              The path to the source file.
    1044  * @param   paParsedNames       Array of parsed names, there are
    1045  *                              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     else
    1077         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.
    10871069 * @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 */
     1074static 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;
    10931079
    10941080    /*
    1095      * Split it up by '='.  Because of the source, which comes last,
     1081     * Split it up by '='.
    10961082     */
    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;
    10991086    for (;;)
    11001087    {
    11011088        const char *pszEqual   = strchr(pszSpec, '=');
    11021089        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);
    11091096        if (!fNeedSlash)
    1110             memcpy(aParsedNames[cParsedNames].szPath, pszSpec, cchName);
     1097            memcpy(pParsed->aNames[pParsed->cNamesWithSrc].szPath, pszSpec, cchName);
    11111098        else
    11121099        {
    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;
    11151102            cchName++;
    11161103        }
    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)
    11221109        {
    11231110            if (!cchName)
    11241111                return rtFsIsoMakerCmdSyntaxError(pOpts, "empty source file name: %s", pszSpecIn);
    11251112            if (cchName == 8 && strcmp(pszSpec, ":remove:") == 0)
    1126                 enmSpecialSrc = kSpecialSrc_Remove;
     1113                pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove;
    11271114            else if (cchName == 13 && strcmp(pszSpec, ":must-remove:") == 0)
    1128                 enmSpecialSrc = kSpecialSrc_MustRemove;
     1115                pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove;
    11291116            break;
    11301117        }
     
    11331120
    11341121    /*
    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.
    11361124     */
    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        }
    11411135
    11421136        /* 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)
    11441138        {
    1145             if (RTVfsChainIsSpec(aParsedNames[iSrc].szPath))
     1139            if (RTVfsChainIsSpec(pParsed->aNames[iSrc].szPath))
    11461140            {
    11471141                uint32_t offError;
    11481142                char *pszFinalPath;
    1149                 int rc = RTVfsChainQueryFinalPath(aParsedNames[iSrc].szPath, &pszFinalPath, &offError);
     1143                int rc = RTVfsChainQueryFinalPath(pParsed->aNames[iSrc].szPath, &pszFinalPath, &offError);
    11501144                if (RT_FAILURE(rc))
    11511145                    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);
    11541148                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);
    11561150                else
    11571151                {
    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++;
    11611155                }
    11621156                RTStrFree(pszFinalPath);
    11631157            }
    11641158#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]))
    11671161            {
    1168                 if (RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[2]))
     1162                if (RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[2]))
    11691163                {
    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;
    11721166                }
    11731167                else
    11741168                {
    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;
    11781172                }
    11791173            }
    11801174#endif
    1181             else if (!RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[0]))
     1175            else if (!RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[0]))
    11821176            {
    1183                 if (aParsedNames[iSrc].cchPath + 2 > sizeof(aParsedNames[iSrc].szPath))
     1177                if (pParsed->aNames[iSrc].cchPath + 2 > sizeof(pParsed->aNames[iSrc].szPath))
    11841178                    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++;
    11881182            }
    11891183        }
    11901184
    11911185        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;
    11951191
    11961192    /*
     
    11991195    for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
    12001196    {
    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 */
     1218static 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 */
     1256static 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 */
     1285static 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 */
     1309static 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;
    12051318
    12061319    /*
    12071320     * Deal with special source filenames used to remove/change stuff.
    12081321     */
    1209     if (   enmSpecialSrc == kSpecialSrc_Remove
    1210         || enmSpecialSrc == kSpecialSrc_MustRemove)
     1322    if (   Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove
     1323        || Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove)
    12111324    {
    12121325        const char *pszFirstNm = NULL;
    12131326        uint32_t    cRemoved   = 0;
    12141327        for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
    1215             if (   aParsedNames[i].cchPath > 0
    1216                 && (aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))
     1328            if (   Parsed.aNames[i].cchPath > 0
     1329                && (Parsed.aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))
    12171330            {
    1218                 pszFirstNm = aParsedNames[i].szPath;
     1331                pszFirstNm = Parsed.aNames[i].szPath;
    12191332                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);
    12221335                if (idxObj != UINT32_MAX)
    12231336                {
    12241337                    int rc = RTFsIsoMakerObjRemove(pOpts->hIsoMaker, idxObj);
    12251338                    if (RT_FAILURE(rc))
    1226                         return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpecIn, rc);
     1339                        return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpec, rc);
    12271340                    cRemoved++;
    12281341                }
    12291342            }
    1230         if (   enmSpecialSrc == kSpecialSrc_MustRemove
     1343        if (   Parsed.enmSrcType  == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove
    12311344            && cRemoved == 0)
    1232             return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpecIn);
     1345            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpec);
    12331346    }
    12341347    /*
     
    12371350    else
    12381351    {
    1239         const char     *pszSrc = aParsedNames[cParsedNames - 1].szPath;
     1352        const char     *pszSrc = Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath;
    12401353        RTFSOBJINFO     ObjInfo;
    12411354        uint32_t        offError;
     
    12471360
    12481361        if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
    1249             return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, aParsedNames);
     1362            return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, &Parsed, NULL /*pidxObj*/);
     1363
    12501364        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
    12521367        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);
    12551371    }
    12561372
     
    12951411
    12961412/**
    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.
    13021414 *
    13031415 * @returns IPRT status code
    13041416 * @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 */
     1418static void rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(PRTFSISOMAKERCMDOPTS pOpts)
    13211419{
    13221420    if (pOpts->cBootCatEntries == 0)
     
    13401438static int rtFsIsoMakerCmdOptEltoritoEnsureSectionEntry(PRTFSISOMAKERCMDOPTS pOpts, bool fForceNew, uint32_t *pidxBootCat)
    13411439{
    1342     rtFsIsoMakerCmdOptEltoritoEnsureValiidationEntry(pOpts);
     1440    rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts);
    13431441
    13441442    uint32_t i = pOpts->cBootCatEntries;
     
    13641462                                                                :          RTFSISOMKCMDELTORITOENTRY::kEntryType_Section;
    13651463        pOpts->aBootCatEntries[i].u.Section.pszImageNameInIso   = NULL;
    1366         pOpts->aBootCatEntries[i].u.Section.idImage             = UINT32_MAX;
     1464        pOpts->aBootCatEntries[i].u.Section.idxImageObj         = UINT32_MAX;
    13671465        pOpts->aBootCatEntries[i].u.Section.fInsertBootInfoTable = false;
    13681466        pOpts->aBootCatEntries[i].u.Section.fBootable           = true;
     
    13801478
    13811479/**
     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 */
     1490static 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/**
    13821513 * Deals with: --eltorito-add-image {file-spec}
    13831514 *
     
    13941525static int rtFsIsoMakerCmdOptEltoritoAddImage(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootImageSpec)
    13951526{
    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;
    13981550}
    13991551
     
    14141566    if (RT_SUCCESS(rc))
    14151567    {
    1416         if (   pOpts->aBootCatEntries[idxBootCat].u.Section.idImage != UINT32_MAX
     1568        if (   pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj != UINT32_MAX
    14171569            || pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso != NULL)
    14181570            return rtFsIsoMakerCmdSyntaxError(pOpts, "boot image already given for current El Torito entry (%#u)", idxBootCat);
    14191571
    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)
    14231574            pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso = pszBootImage;
     1575        pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj;
    14241576    }
    14251577    return rc;
     
    14591611    if (pOpts->cBootCatEntries <= 1)
    14601612    {
    1461         rtFsIsoMakerCmdOptEltoritoEnsureValiidationEntry(pOpts);
     1613        rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts);
    14621614        pOpts->aBootCatEntries[0].u.Validation.idPlatform = idPlatform;
    14631615    }
     
    15751727        pOpts->aBootCatEntries[idxBootCat].u.Section.fInsertBootInfoTable = true;
    15761728    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 */
     1741static 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;
    15771803}
    15781804
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette