VirtualBox

Changeset 67305 in vbox for trunk


Ignore:
Timestamp:
Jun 8, 2017 9:25:39 PM (8 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code.

File:
1 edited

Legend:

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

    r67303 r67305  
    5252*   Defined Constants And Macros                                                                                                 *
    5353*********************************************************************************************************************************/
     54/** Asserts valid handle, returns @a a_rcRet if not. */
     55#define RTFSISOMAKER_ASSER_VALID_HANDLE_RET_EX(a_pThis, a_rcRet) \
     56    do { AssertPtrReturn(a_pThis, a_rcRet); \
     57         AssertPtrReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, a_rcRet); \
     58    } while (0)
     59
    5460/** Asserts valid handle, returns VERR_INVALID_HANDLE if not. */
    55 #define RTFSISOMAKER_ASSER_VALID_HANDLE_RET(a_pThis) \
    56     do { AssertPtrReturn(a_pThis, VERR_INVALID_HANDLE); \
    57          AssertPtrReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, VERR_INVALID_HANDLE); \
    58     } while (0)
     61#define RTFSISOMAKER_ASSER_VALID_HANDLE_RET(a_pThis) RTFSISOMAKER_ASSER_VALID_HANDLE_RET_EX(a_pThis, VERR_INVALID_HANDLE)
    5962
    6063/** The sector size. */
     
    9295 * @{
    9396 */
    94 #define RTFSISOMAKERNAMESPACE_ISO_9660      RT_BIT_32(0)            /**< The primary ISO-9660 namespace. */
    95 #define RTFSISOMAKERNAMESPACE_JOLIET        RT_BIT_32(1)            /**< The joliet namespace. */
    96 #define RTFSISOMAKERNAMESPACE_UDF           RT_BIT_32(2)            /**< The UDF namespace. */
    97 #define RTFSISOMAKERNAMESPACE_HFS           RT_BIT_32(3)            /**< The HFS namespace */
    98 #define RTFSISOMAKERNAMESPACE_ALL           UINT32_C(0x0000000f)    /**< All namespaces. */
    99 #define RTFSISOMAKERNAMESPACE_VALID_MASK    UINT32_C(0x0000000f)    /**< Valid namespace bits. */
     97#define RTFSISOMAKER_NAMESPACE_ISO_9660     RT_BIT_32(0)            /**< The primary ISO-9660 namespace. */
     98#define RTFSISOMAKER_NAMESPACE_JOLIET       RT_BIT_32(1)            /**< The joliet namespace. */
     99#define RTFSISOMAKER_NAMESPACE_UDF          RT_BIT_32(2)            /**< The UDF namespace. */
     100#define RTFSISOMAKER_NAMESPACE_HFS          RT_BIT_32(3)            /**< The HFS namespace */
     101#define RTFSISOMAKER_NAMESPACE_ALL          UINT32_C(0x0000000f)    /**< All namespaces. */
     102#define RTFSISOMAKER_NAMESPACE_VALID_MASK   UINT32_C(0x0000000f)    /**< Valid namespace bits. */
    100103/** @} */
    101104
     
    220223     * Linux behaves a little different when seeing the ER tag. */
    221224    uint8_t                 uRockRidgeLevel;
    222     /** Set if TRANS.TBL files are to be generated for this namespace. */
    223     bool                    fTransTbl;
     225    /** The TRANS.TBL filename if enabled, NULL if disabled.
     226     * When not NULL, this may be pointing to heap or g_szTransTbl. */
     227    char                   *pszTransTbl;
    224228} RTFSISOMAKERNAMESPACE;
    225229/** Pointer to a namespace. */
     
    269273    RTFMODE                 fMode;
    270274
     275    /** Used to make sure things like the boot catalog stays in the image even if
     276     * it's not mapped into any of the namespaces. */
     277    bool                    fNotOrphan;
    271278} RTFSISOMAKEROBJ;
    272279
     
    280287    RTFSISOMAKERSRCTYPE_PATH,
    281288    RTFSISOMAKERSRCTYPE_VFS_FILE,
     289    RTFSISOMAKERSRCTYPE_TRANS_TBL,
    282290    RTFSISOMAKERSRCTYPE_END
    283291} RTFSISOMAKERSRCTYPE;
     
    305313        /** Source VFS file. */
    306314        RTVFSFILE           hVfsFile;
     315        /** The directory the translation table belongs to. */
     316        PRTFSISOMAKERNAME   pTransTblDir;
    307317    } u;
    308318} RTFSISOMAKERFILE;
     
    340350     * after having started to add files. */
    341351    bool                    fSeenContent;
     352    /** Set once we've finalized the image structures.
     353     * After this no more changes are allowed.  */
     354    bool                    fFinalized;
    342355
    343356    /** The primary ISO-9660 namespace. */
     
    358371    /** Amount of file data. */
    359372    uint64_t                cbData;
    360     /** The total image size.
    361      * @todo not sure if this is desirable.  */
    362     uint64_t                cbTotal;
     373    /** Number of volume descriptors. */
     374    uint8_t                 cVolumeDescriptors;
    363375
    364376    /** The 'now' timestamp we use for the whole image.
     
    375387    RTFMODE                 fDefaultDirMode;
    376388
     389    /** The finalized image size. */
     390    uint64_t                cbFinalizedImage;
     391    //PISO9660PRIMARYVOLDESC
    377392} RTFSISOMAKERINT;
    378393/** Pointer to an ISO maker instance. */
     
    388403static const struct
    389404{
    390     /** The RTFSISOMAKERNAMESPACE_XXX indicator.  */
     405    /** The RTFSISOMAKER_NAMESPACE_XXX indicator.  */
    391406    uint32_t        fNamespace;
    392407    /** Offset into RTFSISOMAKERINT of the namespace member. */
     
    398413} g_aRTFsIsoNamespaces[] =
    399414{
    400     {   RTFSISOMAKERNAMESPACE_ISO_9660, RT_OFFSETOF(RTFSISOMAKERINT, PrimaryIso), RT_OFFSETOF(RTFSISOMAKEROBJ, pPrimaryName), "iso-9660" },
    401     {   RTFSISOMAKERNAMESPACE_JOLIET,   RT_OFFSETOF(RTFSISOMAKERINT, Joliet),     RT_OFFSETOF(RTFSISOMAKEROBJ, pJolietName),  "joliet" },
    402     {   RTFSISOMAKERNAMESPACE_UDF,      RT_OFFSETOF(RTFSISOMAKERINT, Udf),        RT_OFFSETOF(RTFSISOMAKEROBJ, pUdfName),     "udf" },
    403     {   RTFSISOMAKERNAMESPACE_HFS,      RT_OFFSETOF(RTFSISOMAKERINT, Hfs),        RT_OFFSETOF(RTFSISOMAKEROBJ, pHfsName),     "hfs" },
     415    {   RTFSISOMAKER_NAMESPACE_ISO_9660, RT_OFFSETOF(RTFSISOMAKERINT, PrimaryIso), RT_OFFSETOF(RTFSISOMAKEROBJ, pPrimaryName), "iso-9660" },
     416    {   RTFSISOMAKER_NAMESPACE_JOLIET,   RT_OFFSETOF(RTFSISOMAKERINT, Joliet),     RT_OFFSETOF(RTFSISOMAKEROBJ, pJolietName),  "joliet" },
     417    {   RTFSISOMAKER_NAMESPACE_UDF,      RT_OFFSETOF(RTFSISOMAKERINT, Udf),        RT_OFFSETOF(RTFSISOMAKEROBJ, pUdfName),     "udf" },
     418    {   RTFSISOMAKER_NAMESPACE_HFS,      RT_OFFSETOF(RTFSISOMAKERINT, Hfs),        RT_OFFSETOF(RTFSISOMAKEROBJ, pHfsName),     "hfs" },
    404419};
    405420
    406421/**
    407  * Translates a single namespace flag (RTFSISOMAKERNAMESPACE_XXX) to an
     422 * Translates a single namespace flag (RTFSISOMAKER_NAMESPACE_XXX) to an
    408423 * index into g_aRTFsIsoNamespaces.
    409424 */
     
    411426{
    412427    /*[0]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    413     /*[RTFSISOMAKERNAMESPACE_ISO_9660] = */ 0,
     428    /*[RTFSISOMAKER_NAMESPACE_ISO_9660] = */ 0,
    414429    /*[2]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    415430    /*[3]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    416     /*[RTFSISOMAKERNAMESPACE_JOLIET]   = */ 1,
     431    /*[RTFSISOMAKER_NAMESPACE_JOLIET]   = */ 1,
    417432    /*[5]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    418433    /*[6]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    419434    /*[7]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    420     /*[RTFSISOMAKERNAMESPACE_UDF]      = */ 2,
     435    /*[RTFSISOMAKER_NAMESPACE_UDF]      = */ 2,
    421436    /*[9]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    422437    /*[10]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     
    426441    /*[14]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    427442    /*[15]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    428     /*[RTFSISOMAKERNAMESPACE_HFS]      = */ 3,
     443    /*[RTFSISOMAKER_NAMESPACE_HFS]      = */ 3,
    429444    /*[17]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
    430445    /*[18]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     
    444459};
    445460
     461/** The default translation table filename. */
     462static char g_szTransTbl[] = "TRANS.TBL";
     463
    446464
    447465/*********************************************************************************************************************************
    448466*   Internal Functions                                                                                                           *
    449467*********************************************************************************************************************************/
     468static int rtFsIsoMakerObjSetName(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace, PRTFSISOMAKEROBJ pObj,
     469                                  PRTFSISOMAKERNAME pParent, const char *pchSpec, size_t cchSpec, PPRTFSISOMAKERNAME ppNewName);
     470static int rtFsIsoMakerObjUnsetName(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace, PRTFSISOMAKEROBJ pObj);
    450471static int rtFsIsoMakerAddUnnamedDirWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKERDIR *ppDir);
    451 
    452 RTDECL(int) RTFsIsoMakerObjSetPath(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t fNamespaces, const char *pszPath);
     472static int rtFsIsoMakerAddUnnamedFileWorker(PRTFSISOMAKERINT pThis, PCRTFSOBJINFO pObjInfo, size_t cbExtra,
     473                                            PRTFSISOMAKERFILE *ppFile);
     474static int rtFsIsoMakerObjRemoveWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj);
     475
    453476
    454477
     
    464487     * Do some integrity checks first.
    465488     */
    466     AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_ISO_9660]].fNamespace == RTFSISOMAKERNAMESPACE_ISO_9660,
     489    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_ISO_9660]].fNamespace == RTFSISOMAKER_NAMESPACE_ISO_9660,
    467490                 VERR_INTERNAL_ERROR_5);
    468     AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_JOLIET]].fNamespace   == RTFSISOMAKERNAMESPACE_JOLIET,
     491    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_JOLIET]].fNamespace   == RTFSISOMAKER_NAMESPACE_JOLIET,
    469492                 VERR_INTERNAL_ERROR_5);
    470     AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_UDF]].fNamespace      == RTFSISOMAKERNAMESPACE_UDF,
     493    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_UDF]].fNamespace      == RTFSISOMAKER_NAMESPACE_UDF,
    471494                 VERR_INTERNAL_ERROR_5);
    472     AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_HFS]].fNamespace      == RTFSISOMAKERNAMESPACE_HFS,
     495    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_HFS]].fNamespace      == RTFSISOMAKER_NAMESPACE_HFS,
    473496                 VERR_INTERNAL_ERROR_5);
    474497
     
    483506        //pThis->fSeenContent               = false;
    484507
    485         pThis->PrimaryIso.fNamespace        = RTFSISOMAKERNAMESPACE_ISO_9660;
     508        pThis->PrimaryIso.fNamespace        = RTFSISOMAKER_NAMESPACE_ISO_9660;
    486509        pThis->PrimaryIso.offName           = RT_OFFSETOF(RTFSISOMAKEROBJ, pPrimaryName);
    487510        pThis->PrimaryIso.uLevel            = 3; /* 30 char names, large files */
    488511        pThis->PrimaryIso.uRockRidgeLevel   = 1;
    489         pThis->PrimaryIso.fTransTbl         = true;
    490         pThis->Joliet.fNamespace            = RTFSISOMAKERNAMESPACE_JOLIET;
     512        pThis->PrimaryIso.pszTransTbl       = g_szTransTbl;
     513        pThis->Joliet.fNamespace            = RTFSISOMAKER_NAMESPACE_JOLIET;
    491514        pThis->Joliet.offName               = RT_OFFSETOF(RTFSISOMAKEROBJ, pJolietName);
    492515        pThis->Joliet.uLevel                = 3;
    493516        //pThis->Joliet.uRockRidgeLevel     = 0;
    494         //pThis->Joliet.fTransTbl           = false;
    495         pThis->Udf.fNamespace               = RTFSISOMAKERNAMESPACE_UDF;
     517        //pThis->Joliet.pszTransTbl         = NULL;
     518        pThis->Udf.fNamespace               = RTFSISOMAKER_NAMESPACE_UDF;
    496519        pThis->Udf.offName                  = RT_OFFSETOF(RTFSISOMAKEROBJ, pUdfName);
    497520        //pThis->Udf.uLevel                 = 0;
    498521        //pThis->Udf.uRockRidgeLevel        = 0;
    499         //pThis->Udf.fTransTbl              = false;
    500         pThis->Hfs.fNamespace               = RTFSISOMAKERNAMESPACE_HFS;
     522        //pThis->Udf.pszTransTbl            = NULL;
     523        pThis->Hfs.fNamespace               = RTFSISOMAKER_NAMESPACE_HFS;
    501524        pThis->Hfs.offName                  = RT_OFFSETOF(RTFSISOMAKEROBJ, pHfsName);
    502525        //pThis->Hfs.uLevel                 = 0;
    503526        //pThis->Hfs.uRockRidgeLevel        = 0;
    504         //pThis->Hfs.fTransTbl              = false;
     527        //pThis->Hfs.pszTransTbl            = NULL;
    505528
    506529        RTListInit(&pThis->ObjectHead);
     
    508531        //pThis->cbData                     = 0;
    509532
    510         pThis->cbTotal                      = _32K /* The system area size. */
    511                                             + RTFSISOMAKER_SECTOR_SIZE /* Primary volume descriptor. */
    512                                             + RTFSISOMAKER_SECTOR_SIZE /* Secondary volume descriptor for joliet. */
    513                                             + RTFSISOMAKER_SECTOR_SIZE /* Terminator descriptor. */;
     533        pThis->cVolumeDescriptors           = 3; /* primary, secondary joliet, terminator. */
    514534
    515535        //pThis->uidDefault                 = 0;
     
    542562        {
    543563            case RTFSISOMAKERSRCTYPE_PATH:
    544                 /* do nothing. */
     564                pFile->u.pszSrcPath = NULL;
     565                break;
     566
     567            case RTFSISOMAKERSRCTYPE_TRANS_TBL:
     568                pFile->u.pTransTblDir = NULL;
    545569                break;
    546570
     
    587611
    588612/**
    589  * Recursively destroy a name space tree.
    590  * @param   pRoot               The root node.
    591  */
    592 static void rtFsIsoMakerDestroyTree(PRTFSISOMAKERNAME pRoot)
    593 {
    594     Assert(!pRoot->pParent);
    595     PRTFSISOMAKERNAME pCur = pRoot;
    596 
    597     for (;;)
    598     {
    599         if (   pCur->pDir
    600             && pCur->pDir->cChildren)
    601             pCur = pCur->pDir->papChildren[pCur->pDir->cChildren - 1];
    602         else
    603         {
    604             PRTFSISOMAKERNAME pNext = pCur->pParent;
    605             rtFsIsoMakerDestroyName(pCur);
    606 
    607             /* Unlink from parent, we're the last entry. */
    608             if (pNext)
    609             {
    610                 Assert(pNext->pDir->cChildren > 0);
    611                 pNext->pDir->cChildren--;
    612                 Assert(pNext->pDir->papChildren[pNext->pDir->cChildren] == pCur);
    613                 pNext->pDir->papChildren[pNext->pDir->cChildren] = NULL;
    614                 pCur = pNext;
    615             }
     613 * Destroys a namespace.
     614 *
     615 * @param   pNamespace          The namespace to destroy.
     616 */
     617static void rtFsIsoMakerDestroyTree(PRTFSISOMAKERNAMESPACE pNamespace)
     618{
     619    /*
     620     * Recursively destroy the tree first.
     621     */
     622    PRTFSISOMAKERNAME pCur = pNamespace->pRoot;
     623    if (pCur)
     624    {
     625        Assert(!pCur->pParent);
     626        for (;;)
     627        {
     628            if (   pCur->pDir
     629                && pCur->pDir->cChildren)
     630                pCur = pCur->pDir->papChildren[pCur->pDir->cChildren - 1];
    616631            else
    617632            {
    618                 Assert(pRoot == pCur);
    619                 break;
     633                PRTFSISOMAKERNAME pNext = pCur->pParent;
     634                rtFsIsoMakerDestroyName(pCur);
     635
     636                /* Unlink from parent, we're the last entry. */
     637                if (pNext)
     638                {
     639                    Assert(pNext->pDir->cChildren > 0);
     640                    pNext->pDir->cChildren--;
     641                    Assert(pNext->pDir->papChildren[pNext->pDir->cChildren] == pCur);
     642                    pNext->pDir->papChildren[pNext->pDir->cChildren] = NULL;
     643                    pCur = pNext;
     644                }
     645                else
     646                {
     647                    Assert(pNamespace->pRoot == pCur);
     648                    break;
     649                }
    620650            }
    621651        }
     652        pNamespace->pRoot = NULL;
     653    }
     654
     655    /*
     656     * Free the translation table filename if allocated.
     657     */
     658    if (pNamespace->pszTransTbl)
     659    {
     660        if (pNamespace->pszTransTbl != g_szTransTbl)
     661            RTMemFree(pNamespace->pszTransTbl);
     662        pNamespace->pszTransTbl = NULL;
    622663    }
    623664}
     
    631672static void rtFsIsoMakerDestroy(PRTFSISOMAKERINT pThis)
    632673{
    633     rtFsIsoMakerDestroyTree(pThis->PrimaryIso.pRoot);
    634     rtFsIsoMakerDestroyTree(pThis->Joliet.pRoot);
    635     rtFsIsoMakerDestroyTree(pThis->Udf.pRoot);
    636     rtFsIsoMakerDestroyTree(pThis->Hfs.pRoot);
     674    rtFsIsoMakerDestroyTree(&pThis->PrimaryIso);
     675    rtFsIsoMakerDestroyTree(&pThis->Joliet);
     676    rtFsIsoMakerDestroyTree(&pThis->Udf);
     677    rtFsIsoMakerDestroyTree(&pThis->Hfs);
    637678
    638679    PRTFSISOMAKEROBJ pCur;
     
    727768    {
    728769        if (uJolietLevel == 0)
    729             pThis->cbTotal -= RTFSISOMAKER_SECTOR_SIZE;
     770            pThis->cVolumeDescriptors--;
    730771        else if (pThis->Joliet.uLevel == 0)
    731             pThis->cbTotal += RTFSISOMAKER_SECTOR_SIZE;
     772            pThis->cVolumeDescriptors++;
    732773        pThis->Joliet.uLevel = uJolietLevel;
    733774    }
     
    785826 */
    786827
    787 #if 0
    788 /**
    789  * Gets the pointer to the root member for the given namespace.
    790  *
    791  * @returns Pointer to root pointer.
    792  * @param   pThis               The ISO maker instance.
    793  * @param   fNamespace          The namespace which name to find.
    794  */
    795 static PPRTFSISOMAKERNAME rtFsIsoMakerGetRootForNamespace(PRTFSISOMAKERINT pThis, uint32_t fNamespace)
    796 {
    797     Assert(RT_IS_POWER_OF_TWO(fNamespace));
    798     Assert(fNamespace);
    799     Assert(fNamespace <= RTFSISOMAKERNAMESPACE_HFS);
    800     return (PPRTFSISOMAKERNAME)((uintptr_t)pThis + g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[fNamespace]].offRoot);
    801 }
    802 #endif
    803 
    804828
    805829/**
     
    842866    return NULL;
    843867}
     868
     869
     870/**
     871 * Compares the two names according to ISO-9660 directory sorting rules.
     872 *
     873 * As long as we don't want to do case insensitive joliet sorting, this works
     874 * for joliet names to, I think.
     875 *
     876 * @returns 0 if equal, -1 if pszName1 comes first, 1 if pszName2 comes first.
     877 * @param   pszName1            The first name.
     878 * @param   pszName2            The second name.
     879 */
     880DECLINLINE(int) rtFsIsoMakerCompareIso9660Names(const char *pszName1, const char *pszName2)
     881{
     882    for (;;)
     883    {
     884        char const ch1 = *pszName1++;
     885        char const ch2 = *pszName2++;
     886        if (ch1 == ch2)
     887        {
     888            if (ch1)
     889            { /* likely */ }
     890            else
     891                return 0;
     892        }
     893        else if (ch1 == ';' || ch2 == ';')
     894            return ch1 == ';' ? -1 : 1;
     895        else if (ch1 == '.' || ch2 == '.')
     896            return ch1 == '.' ? -1 : 1;
     897        else
     898            return (unsigned char)ch1 < (unsigned char)ch2 ? -1 : 1;
     899    }
     900}
     901
     902
     903/**
     904 * Finds the index into papChildren where the given name should be inserted.
     905 *
     906 * @returns Index of the given name.
     907 * @param   pNamespace          The namspace.
     908 * @param   pParent             The parent namespace node.
     909 * @param   pszName             The name.
     910 */
     911static uint32_t rtFsIsoMakerFindInsertIndex(PRTFSISOMAKERNAMESPACE pNamespace, PRTFSISOMAKERNAME pParent, const char *pszName)
     912{
     913    uint32_t idxRet = pParent->pDir->cChildren;
     914    if (idxRet > 0)
     915    {
     916        /*
     917         * The idea is to do binary search using a namespace specific compare
     918         * function.  However, it looks like we can get away with using the
     919         * same compare function for all namespaces.
     920         */
     921        uint32_t            idxStart = 0;
     922        uint32_t            idxEnd   = idxRet;
     923        PPRTFSISOMAKERNAME  papChildren = pParent->pDir->papChildren;
     924        switch (pNamespace->fNamespace)
     925        {
     926            case RTFSISOMAKER_NAMESPACE_ISO_9660:
     927            case RTFSISOMAKER_NAMESPACE_JOLIET:
     928            case RTFSISOMAKER_NAMESPACE_UDF:
     929            case RTFSISOMAKER_NAMESPACE_HFS:
     930                for (;;)
     931                {
     932                    idxRet = idxStart + (idxEnd - idxStart) / 2;
     933                    PRTFSISOMAKERNAME pCur = papChildren[idxRet];
     934                    int iDiff = rtFsIsoMakerCompareIso9660Names(pszName, pCur->szName);
     935                    if (iDiff < 0)
     936                    {
     937                        if (idxRet > idxStart)
     938                            idxEnd = idxRet;
     939                        else
     940                            break;
     941                    }
     942                    else
     943                    {
     944                        idxRet++;
     945                        if (   iDiff != 0
     946                            && idxRet < idxEnd)
     947                            idxStart = idxRet;
     948                        else
     949                            break;
     950                    }
     951                }
     952                break;
     953
     954            default:
     955                AssertFailed();
     956                break;
     957        }
     958    }
     959    return idxRet;
     960}
     961
    844962
    845963
     
    9111029        }
    9121030    return NULL;
     1031}
     1032
     1033
     1034/**
     1035 * Walks the given path by specified object names in a namespace.
     1036 *
     1037 * @returns IPRT status code.
     1038 * @param   pNamespace  The namespace to walk the path in.
     1039 * @param   pszPath     The path to walk.
     1040 * @param   ppName      Where to return the name node that the path ends with.
     1041 */
     1042static int rtFsIsoMakerWalkPathBySpec(PRTFSISOMAKERNAMESPACE pNamespace, const char *pszPath, PPRTFSISOMAKERNAME ppName)
     1043{
     1044    *ppName = NULL;
     1045    AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INVALID_NAME);
     1046
     1047    /*
     1048     * Deal with the special case of the root.
     1049     */
     1050    while (RTPATH_IS_SLASH(*pszPath))
     1051        pszPath++;
     1052    AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4);
     1053
     1054    PRTFSISOMAKERNAME pCur = pNamespace->pRoot;
     1055    if (!pCur)
     1056        return *pszPath ? VERR_PATH_NOT_FOUND : VERR_FILE_NOT_FOUND;
     1057    if (!*pszPath)
     1058    {
     1059        *ppName = pCur;
     1060        return VINF_SUCCESS;
     1061    }
     1062
     1063    /*
     1064     * Now, do the rest of the path.
     1065     */
     1066    for (;;)
     1067    {
     1068        /*
     1069         * Find the end of the component.
     1070         */
     1071        char ch;
     1072        size_t cchComponent = 0;
     1073        while ((ch = pszPath[cchComponent]) != '\0' && RTPATH_IS_SLASH(ch))
     1074            cchComponent++;
     1075        if (!cchComponent)
     1076        {
     1077            *ppName = pCur;
     1078            return VINF_SUCCESS;
     1079        }
     1080
     1081        size_t offNext = cchComponent;
     1082        while (RTPATH_IS_SLASH(ch))
     1083            ch = pszPath[offNext++];
     1084
     1085        /*
     1086         * Deal with dot and dot-dot.
     1087         */
     1088        if (cchComponent == 1 && pszPath[0] == '.')
     1089        { /* nothing to do */ }
     1090        else if (cchComponent == 2 && pszPath[0] == '.' && pszPath[1] == '.')
     1091        {
     1092            if (pCur->pParent)
     1093                pCur = pCur->pParent;
     1094        }
     1095        /*
     1096         * Look up the name.
     1097         */
     1098        else
     1099        {
     1100            PRTFSISOMAKERNAME pChild = rtFsIsoMakerFindEntryInDirBySpec(pCur, pszPath, cchComponent);
     1101            if (!pChild)
     1102                return pszPath[offNext] ? VERR_PATH_NOT_FOUND : VERR_FILE_NOT_FOUND;
     1103            if (   (offNext > cchComponent)
     1104                && !pChild->pDir)
     1105                return VERR_NOT_A_DIRECTORY;
     1106            pCur = pChild;
     1107        }
     1108
     1109        /*
     1110         * Skip ahead in the path.
     1111         */
     1112        pszPath += offNext;
     1113    }
    9131114}
    9141115
     
    11121313             * This one is a lot of work, so separate function.
    11131314             */
    1114             case RTFSISOMAKERNAMESPACE_ISO_9660:
     1315            case RTFSISOMAKER_NAMESPACE_ISO_9660:
    11151316                return rtFsIsoMakerNormalizeNameForPrimaryIso9660(pThis, pParent, pchSrc, cchSrc, fIsDir, pszDst, cbDst, pcchDst);
    11161317
     
    11181319             * At the moment we don't give darn about UCS-2 limitations here...
    11191320             */
    1120             case RTFSISOMAKERNAMESPACE_JOLIET:
     1321            case RTFSISOMAKER_NAMESPACE_JOLIET:
    11211322            {
    11221323/** @todo Joliet name limit and check for duplicates.   */
     
    11281329            }
    11291330
    1130             case RTFSISOMAKERNAMESPACE_UDF:
    1131             case RTFSISOMAKERNAMESPACE_HFS:
     1331            case RTFSISOMAKER_NAMESPACE_UDF:
     1332            case RTFSISOMAKER_NAMESPACE_HFS:
    11321333                AssertFailedReturn(VERR_NOT_IMPLEMENTED);
    11331334
     
    11501351
    11511352/**
     1353 * Creates a TRANS.TBL file object for a newly named directory.
     1354 *
     1355 * The file is associated with the namespace node for the directory.  The file
     1356 * will be generated on the fly from the directory object.
     1357 *
     1358 * @returns IPRT status code.
     1359 * @param   pThis       The ISO maker instance.
     1360 * @param   pNamespace  The namespace.
     1361 * @param   pDirName    The new name space node for the directory.
     1362 */
     1363static int rtFsIsoMakerAddTransTblFileToNewDir(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace,
     1364                                               PRTFSISOMAKERNAME pDirName)
     1365{
     1366    /*
     1367     * Create a file object for it.
     1368     */
     1369    PRTFSISOMAKERFILE pFile;
     1370    int rc = rtFsIsoMakerAddUnnamedFileWorker(pThis, NULL, 0, &pFile);
     1371    if (RT_SUCCESS(rc))
     1372    {
     1373        pFile->enmSrcType     = RTFSISOMAKERSRCTYPE_TRANS_TBL;
     1374        pFile->u.pTransTblDir = pDirName;
     1375        pDirName->pDir->pTransTblFile = pFile;
     1376
     1377        /*
     1378         * Add it to the directory.
     1379         */
     1380        rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pFile->Core, pDirName,
     1381                                    pNamespace->pszTransTbl, strlen(pNamespace->pszTransTbl), NULL /*ppNewName*/);
     1382        if (RT_SUCCESS(rc))
     1383            return VINF_SUCCESS;
     1384
     1385        /*
     1386         * Bail.
     1387         */
     1388        pDirName->pDir->pTransTblFile = NULL;
     1389        rtFsIsoMakerObjRemoveWorker(pThis, &pFile->Core);
     1390    }
     1391    return rc;
     1392}
     1393
     1394
     1395/**
    11521396 * Sets the name of an object in a namespace.
    11531397 *
    1154  * The object cannot currently have a name in that namespace.
     1398 * If the object is already named in the name space, it will first be removed
     1399 * from that namespace.  Should we run out of memory or into normalization
     1400 * issues after removing it, its original state will _not_ be restored.
    11551401 *
    11561402 * @returns IPRT status code.
     
    11671413{
    11681414    Assert(cchSpec < _32K);
     1415
     1416    /*
     1417     * If the object is already named, unset that name before continuing.
     1418     */
     1419    if (*rtFsIsoMakerObjGetNameForNamespace(pObj, pNamespace))
     1420    {
     1421        int rc = rtFsIsoMakerObjUnsetName(pThis, pNamespace, pObj);
     1422        if (RT_FAILURE(rc))
     1423            return rc;
     1424    }
    11691425
    11701426    /*
     
    12461502                pDir->papChildren   = NULL;
    12471503                pDir->pTransTblFile = NULL;
    1248                 /** @todo TRANS.TBL files. */
    1249 
    12501504                pName->pDir = pDir;
     1505
     1506                /* Create the TRANS.TBL file object and enter it into this directory as the first entry. */
     1507                if (pNamespace->pszTransTbl)
     1508                {
     1509                    rc = rtFsIsoMakerAddTransTblFileToNewDir(pThis, pNamespace, pName);
     1510                    if (RT_FAILURE(rc))
     1511                    {
     1512                        RTMemFree(pName);
     1513                        return rc;
     1514                    }
     1515                }
    12511516            }
    12521517
    12531518            /*
    1254              * Do the linking and stats.
     1519             * Do the linking and stats.  We practice insertion sorting.
    12551520             */
    12561521            if (pParent)
    1257                 pParent->pDir->papChildren[pParent->pDir->cChildren++] = pName;
     1522            {
     1523                uint32_t idxName   = rtFsIsoMakerFindInsertIndex(pNamespace, pParent, pName->szName);
     1524                uint32_t cChildren = pParent->pDir->cChildren;
     1525                if (idxName < cChildren)
     1526                    memmove(&pParent->pDir->papChildren[idxName + 1], &pParent->pDir->papChildren[idxName],
     1527                            (cChildren - idxName) * sizeof(pParent->pDir->papChildren[0]));
     1528                pParent->pDir->papChildren[idxName] = pName;
     1529                pParent->pDir->cChildren++;
     1530            }
    12581531            else
    12591532                pNamespace->pRoot = pName;
     
    12731546
    12741547
    1275 static int rtFsIsoMakerPathToParent(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace, const char *pszPath,
    1276                                     PPRTFSISOMAKERNAME ppParent, const char **ppszEntry, size_t *pcchEntry)
     1548/**
     1549 * Walks the path up to the parent, creating missing directories as needed.
     1550 *
     1551 * As usual, we walk the specified names rather than the mangled ones.
     1552 *
     1553 * @returns IPRT status code.
     1554 * @param   pThis       The ISO maker instance.
     1555 * @param   pNamespace  The namespace to walk.
     1556 * @param   pszPath     The path to walk.
     1557 * @param   ppParent    Where to return the pointer to the parent
     1558 *                      namespace node.
     1559 * @param   ppszEntry   Where to return the pointer to the final name component.
     1560 * @param   pcchEntry   Where to return the length of the final name component.
     1561 */
     1562static int rtFsIsoMakerCreatePathToParent(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace, const char *pszPath,
     1563                                          PPRTFSISOMAKERNAME ppParent, const char **ppszEntry, size_t *pcchEntry)
    12771564{
    12781565    int rc;
     
    12841571    while (RTPATH_IS_SLASH(*pszPath))
    12851572        pszPath++;
    1286     AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4);
     1573    AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4); /* We should not be called on a root path. */
    12871574
    12881575    PRTFSISOMAKERNAME pParent = pNamespace->pRoot;
     
    13571644                pParent = pParent->pParent;
    13581645        }
     1646        /*
     1647         * Look it up.
     1648         */
    13591649        else
    13601650        {
    1361             /*
    1362              * Look it up.
    1363              */
    13641651            PRTFSISOMAKERNAME pChild = rtFsIsoMakerFindEntryInDirBySpec(pParent, pszPath, cchComponent);
    13651652            if (pChild)
    1366                 pParent = pChild;
     1653            {
     1654                if (pChild->pDir)
     1655                    pParent = pChild;
     1656                else
     1657                    return VERR_NOT_A_DIRECTORY;
     1658            }
    13671659            else
    13681660            {
     
    14271719    int                 rc;
    14281720    if (pszPath[1] != '\0')
    1429         rc = rtFsIsoMakerPathToParent(pThis, pNamespace, pszPath, &pParent, &pszEntry, &cchEntry);
     1721        rc = rtFsIsoMakerCreatePathToParent(pThis, pNamespace, pszPath, &pParent, &pszEntry, &cchEntry);
    14301722    else
    14311723    {
     
    15241816
    15251817
     1818
     1819
     1820
    15261821/*
    15271822 *
     
    15691864
    15701865/**
     1866 * Resolves a path into a object ID.
     1867 *
     1868 * This will be doing the looking up using the specified object names rather
     1869 * than the version adjusted and mangled according to the namespace setup.
     1870 *
     1871 * @returns The object ID corresponding to @a pszPath, or UINT32_MAX if not
     1872 *          found or invalid parameters.
     1873 * @param   hIsoMaker           The ISO maker instance.
     1874 * @param   fNamespaces         The namespace to resolve @a pszPath in.  It's
     1875 *                              possible to specify multiple namespaces here, of
     1876 *                              course, but that's inefficient.
     1877 * @param   pszPath             The path to the object.
     1878 */
     1879RTDECL(uint32_t) RTFsIsoMakerGetObjIdxForPath(RTFSISOMAKER hIsoMaker, uint32_t fNamespaces, const char *pszPath)
     1880{
     1881    /*
     1882     * Validate input.
     1883     */
     1884    PRTFSISOMAKERINT pThis = hIsoMaker;
     1885    RTFSISOMAKER_ASSER_VALID_HANDLE_RET_EX(pThis, UINT32_MAX);
     1886
     1887    /*
     1888     * Do the searching.
     1889     */
     1890    for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIsoNamespaces); i++)
     1891        if (fNamespaces & g_aRTFsIsoNamespaces[i].fNamespace)
     1892        {
     1893            PRTFSISOMAKERNAMESPACE pNamespace = (PRTFSISOMAKERNAMESPACE)((uintptr_t)pThis + g_aRTFsIsoNamespaces[i].offNamespace);
     1894            if (pNamespace->pRoot)
     1895            {
     1896                PRTFSISOMAKERNAME pName;
     1897                int rc = rtFsIsoMakerWalkPathBySpec(pNamespace, pszPath, &pName);
     1898                if (RT_SUCCESS(rc))
     1899                    return pName->pObj->idxObj;
     1900            }
     1901        }
     1902
     1903    return UINT32_MAX;
     1904}
     1905
     1906
     1907/**
    15711908 * Removes the specified object from the image.
     1909 *
     1910 * This is a worker for RTFsIsoMakerObjRemove and
     1911 * rtFsIsoMakerFinalizeRemoveOrphans.
    15721912 *
    15731913 * @returns IPRT status code.
    15741914 * @param   hIsoMaker           The ISO maker instance.
    1575  * @param   idxObj              The index of the object to remove.
    1576  */
    1577 RTDECL(int) RTFsIsoMakerObjRemove(RTFSISOMAKER hIsoMaker, uint32_t idxObj)
    1578 {
    1579     /*
    1580      * Validate and translate input.
    1581      */
    1582     PRTFSISOMAKERINT pThis = hIsoMaker;
    1583     RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
    1584     PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj);
    1585     AssertReturn(pObj, VERR_OUT_OF_RANGE);
    1586 
     1915 * @param   pObj                The object to remove from the image.
     1916 */
     1917static int rtFsIsoMakerObjRemoveWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj)
     1918{
    15871919    /*
    15881920     * Remove the object from all name spaces.
     
    16121944        rtFsIsoMakerObjDestroy(pObj);
    16131945    }
    1614 
    16151946    return rc;
     1947}
     1948
     1949
     1950/**
     1951 * Removes the specified object from the image.
     1952 *
     1953 * @returns IPRT status code.
     1954 * @param   hIsoMaker           The ISO maker instance.
     1955 * @param   idxObj              The index of the object to remove.
     1956 */
     1957RTDECL(int) RTFsIsoMakerObjRemove(RTFSISOMAKER hIsoMaker, uint32_t idxObj)
     1958{
     1959    /*
     1960     * Validate and translate input.
     1961     */
     1962    PRTFSISOMAKERINT pThis = hIsoMaker;
     1963    RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     1964    PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj);
     1965    AssertReturn(pObj, VERR_OUT_OF_RANGE);
     1966    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
     1967
     1968    /*
     1969     * Call worker.
     1970     */
     1971    return rtFsIsoMakerObjRemoveWorker(pThis, pObj);
    16161972}
    16171973
     
    16291985 * @param   idxObj              The configuration index of to name.
    16301986 * @param   fNamespaces         The namespaces to apply the path to
    1631  *                              (RTFSISOMAKERNAMESPACE_XXX).
     1987 *                              (RTFSISOMAKER_NAMESPACE_XXX).
    16321988 * @param   pszPath             The path.
    16331989 */
     
    16391995    PRTFSISOMAKERINT pThis = hIsoMaker;
    16401996    RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
    1641     AssertReturn(!(fNamespaces & ~RTFSISOMAKERNAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
     1997    AssertReturn(!(fNamespaces & ~RTFSISOMAKER_NAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
    16421998    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    16431999    AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INVALID_NAME);
    16442000    PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj);
    16452001    AssertReturn(pObj, VERR_OUT_OF_RANGE);
     2002    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    16462003
    16472004    /*
     
    16712028 * The name will be transformed as necessary.
    16722029 *
    1673  * The initial implementation does not allow this function to be called more
    1674  * than once on an object.
    1675  *
    16762030 * @returns IPRT status code.
    16772031 * @param   hIsoMaker           The ISO maker handle.
     
    16792033 * @param   idxParentObj        The parent directory object.
    16802034 * @param   fNamespaces         The namespaces to apply the path to
    1681  *                              (RTFSISOMAKERNAMESPACE_XXX).
     2035 *                              (RTFSISOMAKER_NAMESPACE_XXX).
    16822036 * @param   pszName             The name.
    16832037 */
     
    16902044    PRTFSISOMAKERINT pThis = hIsoMaker;
    16912045    RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
    1692     AssertReturn(!(fNamespaces & ~RTFSISOMAKERNAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
     2046    AssertReturn(!(fNamespaces & ~RTFSISOMAKER_NAMESPACE_VALID_MASK), VERR_INVALID_FLAGS);
    16932047    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    16942048    size_t cchName = strlen(pszName);
     
    16992053    PRTFSISOMAKEROBJ pParentObj = rtFsIsoMakerIndexToObj(pThis, idxParentObj);
    17002054    AssertReturn(pParentObj, VERR_OUT_OF_RANGE);
     2055    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    17012056
    17022057    /*
     
    17382093                                     RTFSISOMAKEROBJTYPE enmType, PCRTFSOBJINFO pObjInfo)
    17392094{
     2095    Assert(!pThis->fFinalized);
    17402096    AssertReturn(pThis->cObjects < RTFSISOMAKER_MAX_OBJECTS, VERR_OUT_OF_RANGE);
     2097
    17412098    pObj->enmType       = enmType;
    17422099    pObj->pPrimaryName  = NULL;
     
    17452102    pObj->pHfsName      = NULL;
    17462103    pObj->idxObj        = pThis->cObjects++;
     2104    pObj->fNotOrphan    = false;
    17472105    if (pObjInfo)
    17482106    {
     
    18102168    RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
    18112169    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
     2170    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    18122171
    18132172    PRTFSISOMAKERDIR pDir;
     
    18402199    if (RT_SUCCESS(rc))
    18412200    {
    1842         rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKERNAMESPACE_ALL, pszDir);
     2201        rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKER_NAMESPACE_ALL, pszDir);
    18432202        if (RT_SUCCESS(rc))
    18442203        {
     
    19032262    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
    19042263    *pidxObj = UINT32_MAX;
     2264    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    19052265
    19062266    /*
     
    19482308    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
    19492309    *pidxObj = UINT32_MAX;
     2310    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    19502311
    19512312    /*
     
    20042365    if (RT_SUCCESS(rc))
    20052366    {
    2006         rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKERNAMESPACE_ALL, pszFile);
     2367        rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKER_NAMESPACE_ALL, pszFile);
    20072368        if (RT_SUCCESS(rc))
    20082369        {
     
    20412402    if (RT_SUCCESS(rc))
    20422403    {
    2043         rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKERNAMESPACE_ALL, pszFile);
     2404        rc = RTFsIsoMakerObjSetPath(hIsoMaker, idxObj, RTFSISOMAKER_NAMESPACE_ALL, pszFile);
    20442405        if (RT_SUCCESS(rc))
    20452406        {
     
    20532414}
    20542415
     2416
     2417
     2418
     2419
     2420/*
     2421 *
     2422 * Image finalization.
     2423 * Image finalization.
     2424 * Image finalization.
     2425 *
     2426 */
     2427
     2428
     2429/**
     2430 * Remove any orphaned object from the disk.
     2431 *
     2432 * @returns IPRT status code.
     2433 * @param   pThis               The ISO maker instance.
     2434 */
     2435static int rtFsIsoMakerFinalizeRemoveOrphans(PRTFSISOMAKERINT pThis)
     2436{
     2437    for (;;)
     2438    {
     2439        uint32_t         cRemoved = 0;
     2440        PRTFSISOMAKEROBJ pCur;
     2441        PRTFSISOMAKEROBJ pNext;
     2442        RTListForEachSafe(&pThis->ObjectHead, pCur, pNext, RTFSISOMAKEROBJ, Entry)
     2443        {
     2444            if (   pCur->pPrimaryName
     2445                || pCur->pJolietName
     2446                || pCur->pUdfName
     2447                || pCur->pHfsName
     2448                || pCur->fNotOrphan)
     2449            { /* likely */ }
     2450            else
     2451            {
     2452                int rc = rtFsIsoMakerObjRemoveWorker(pThis, pCur);
     2453                if (RT_SUCCESS(rc))
     2454                    cRemoved++;
     2455                else
     2456                    return rc;
     2457            }
     2458        }
     2459        if (!cRemoved)
     2460            return VINF_SUCCESS;
     2461    }
     2462}
     2463
     2464
     2465/**
     2466 * Finalizes the El Torito boot stuff.
     2467 *
     2468 * This includes generating the boot catalog data and fixing the location of all
     2469 * related image files.
     2470 *
     2471 * @returns IPRT status code.
     2472 * @param   pThis               The ISO maker instance.
     2473 * @param   poffData            The data offset (in/out).
     2474 */
     2475static int rtFsIsoMakerFinalizeBootStuff(PRTFSISOMAKERINT pThis, uint64_t *poffData)
     2476{
     2477    RT_NOREF(pThis, poffData);
     2478    return VINF_SUCCESS;
     2479}
     2480
     2481
     2482/**
     2483 * Finalizes directories and related stuff.
     2484 *
     2485 * This will not generate actual directory data, but calculate the size of it
     2486 * once it's generated.  Ditto for the path tables.  The exception is the rock
     2487 * ridge spill file, which will be generated in memory.
     2488 *
     2489 * @returns IPRT status code.
     2490 * @param   pThis               The ISO maker instance.
     2491 * @param   poffData            The data offset (in/out).
     2492 */
     2493static int rtFsIsoMakerFinalizeDirectories(PRTFSISOMAKERINT pThis, uint64_t *poffData)
     2494{
     2495    RT_NOREF(pThis, poffData);
     2496    return VINF_SUCCESS;
     2497}
     2498
     2499
     2500/**
     2501 * Finalizes data allocations.
     2502 *
     2503 * This will set the RTFSISOMAKERFILE::offData members.
     2504 *
     2505 * @returns IPRT status code.
     2506 * @param   pThis               The ISO maker instance.
     2507 * @param   poffData            The data offset (in/out).
     2508 */
     2509static int rtFsIsoMakerFinalizeData(PRTFSISOMAKERINT pThis, uint64_t *poffData)
     2510{
     2511    RT_NOREF(pThis, poffData);
     2512    return VINF_SUCCESS;
     2513}
     2514
     2515
     2516/**
     2517 * Finalizes the volume descriptors.
     2518 *
     2519 * This will set the RTFSISOMAKERFILE::offData members.
     2520 *
     2521 * @returns IPRT status code.
     2522 * @param   pThis               The ISO maker instance.
     2523 */
     2524static int rtFsIsoMakerFinalizeVolumeDescriptors(PRTFSISOMAKERINT pThis)
     2525{
     2526    RT_NOREF(pThis);
     2527    return VINF_SUCCESS;
     2528}
     2529
     2530
     2531/**
     2532 * Finalizes the image.
     2533 *
     2534 * @returns IPRT status code.
     2535 * @param   hIsoMaker       The ISO maker handle.
     2536 */
     2537RTDECL(int) RTFsIsoMakerFinalize(RTFSISOMAKER hIsoMaker)
     2538{
     2539    PRTFSISOMAKERINT pThis = hIsoMaker;
     2540    RTFSISOMAKER_ASSER_VALID_HANDLE_RET(pThis);
     2541    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
     2542
     2543    /*
     2544     * Remove orphaned objects.
     2545     */
     2546    int rc = rtFsIsoMakerFinalizeRemoveOrphans(pThis);
     2547    if (RT_FAILURE(rc))
     2548        return rc;
     2549
     2550    /*
     2551     * If there is any boot related stuff to be included, it ends up right after
     2552     * the descriptors.
     2553     */
     2554    uint64_t offData = _32K + pThis->cVolumeDescriptors * RTFSISOMAKER_SECTOR_SIZE;
     2555    rc = rtFsIsoMakerFinalizeBootStuff(pThis, &offData);
     2556    if (RT_SUCCESS(rc))
     2557    {
     2558        rc = rtFsIsoMakerFinalizeDirectories(pThis, &offData);
     2559        if (RT_SUCCESS(rc))
     2560        {
     2561            rc = rtFsIsoMakerFinalizeData(pThis, &offData);
     2562            if (RT_SUCCESS(rc))
     2563            {
     2564                pThis->cbFinalizedImage = offData;
     2565
     2566                /*
     2567                 * Finally, finalize the volume descriptors.
     2568                 */
     2569                rc = rtFsIsoMakerFinalizeVolumeDescriptors(pThis);
     2570                if (RT_SUCCESS(rc))
     2571                {
     2572                    pThis->fFinalized = true;
     2573                    return VINF_SUCCESS;
     2574                }
     2575            }
     2576        }
     2577    }
     2578    return rc;
     2579}
     2580
     2581
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