VirtualBox

Changeset 67281 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 7, 2017 1:01:09 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

    r67278 r67281  
    6262/** Maximum number of objects. */
    6363#define RTFSISOMAKER_MAX_OBJECTS            _16M
     64/** Maximum number of objects per directory. */
     65#define RTFSISOMAKER_MAX_OBJECTS_PER_DIR    _256K /**< @todo check limit */
     66
    6467/** UTF-8 name buffer.  */
    6568#define RTFSISOMAKER_MAX_NAME_BUF           768
     
    7881/** Pointer to an ISO maker object name space node. */
    7982typedef struct RTFSISOMAKERNAME *PRTFSISOMAKERNAME;
     83/** Pointer to an ISO maker object name space node pointer. */
     84typedef PRTFSISOMAKERNAME *PPRTFSISOMAKERNAME;
    8085/** Pointer to a common ISO image maker file system object. */
    8186typedef struct RTFSISOMAKEROBJ *PRTFSISOMAKEROBJ;
     
    120125    uint32_t                cChildren;
    121126    /** Sorted array of children. */
    122     PRTFSISOMAKERNAME      *papChildren;
     127    PPRTFSISOMAKERNAME      papChildren;
    123128
    124129    /** The translate table file. */
     
    162167    /** The depth in the namespace tree of this name. */
    163168    uint8_t                 uDepth;
    164     /** Set if pszTransNm is allocated separately. */
     169    /** Set if pszTransNm is allocated separately.  Normally same as pszSpecNm. */
     170    bool                    fRockRidgeNmAlloced : 1;
     171    /** Set if pszTransNm is allocated separately.  Normally same as pszSpecNm. */
    165172    bool                    fTransNmAlloced : 1;
    166     /** Set if pszTransNm is allocated separately. */
    167     bool                    fRockRidgeNmAlloced : 1;
    168173
    169174/** @todo more rock ridge info here.    */
     
    174179    char                    szName[RT_FLEXIBLE_ARRAY];
    175180} RTFSISOMAKERNAME;
     181
     182/**
     183 * A ISO maker namespace.
     184 */
     185typedef struct RTFSISOMAKERNAMESPACE
     186{
     187    /** The namespace root. */
     188    RTFSISOMAKERNAME        pRoot;
     189    /** Total number of name nodes in the namespace. */
     190    uint32_t                cNames;
     191    /** Total number of directories in the namespace. */
     192    uint32_t                cDirs;
     193    /** The namespace selector (RTFSISOMAKER_NAMESPACE_XXX). */
     194    uint32_t                fNamespace;
     195    /** The configuration level for this name space.
     196     *     - For UDF and HFS namespaces this is either @c true or @c false.
     197     *     - For the primary ISO-9660 namespace this is 1, 2, or 3.
     198     *     - For the joliet namespace this 0 (joliet disabled), 1, 2, or 3. */
     199    uint8_t                 uLevel;
     200    /** The rock ridge level: 1 - enabled; 2 - with ER tag.
     201     * Linux behaves a little different when seeing the ER tag. */
     202    uint8_t                 uRockRidgeLevel;
     203    /** Set if TRANS.TBL files are to be generated for this namespace. */
     204} RTFSISOMAKERNAMESPACE;
     205/** Pointer to a namespace. */
     206typedef RTFSISOMAKERNAMESPACE *PRTFSISOMAKERNAMESPACE;
    176207
    177208
     
    272303     * @todo support mkisofs level 4 (ISO-9660:1990, version 2). */
    273304    uint8_t                 uIsoLevel;
    274     /** The ISO rock ridge level: 1 - enabled; 2 - with ER tag.
    275      * Linux behaves a little different when seeing the ER tag. */
    276     uint8_t                 uRockRidgeLevel;
    277305    /** The joliet UCS level (1, 2, or 3), 0 if joliet is not enabled. */
    278306    uint8_t                 uJolietLevel;
    279     /** The joliet rock ridge level: 1 - enabled; 2 - with ER tag.
    280      * @note Nobody seems to do rock ridge with joliet, so this is highly
    281      *       expermental and here just because we can. */
    282     uint8_t                 uJolietRockRidgeLevel;
    283307    /** Enables UDF.
    284308     * @remarks not yet implemented. */
     
    289313    /** @} */
    290314
    291     /** The root of the primary ISO-9660 name space. */
    292     PRTFSISOMAKERNAME       pPrimaryIsoRoot;
    293     /** The root of the joliet name space. */
    294     PRTFSISOMAKERNAME       pJolietRoot;
    295     /** The root of the UDF name space. */
    296     PRTFSISOMAKERNAME       pUdfRoot;
    297     /** The root of the hybrid HFS name space. */
    298     PRTFSISOMAKERNAME       pHfsRoot;
     315    /** The primary ISO-9660 namespace. */
     316    RTFSISOMAKERNAMESPACE   PrimaryIso;
     317    /** The joliet namespace. */
     318    RTFSISOMAKERNAMESPACE   Joliet;
     319    /** The UDF namespace. */
     320    RTFSISOMAKERNAMESPACE   Udf;
     321    /** The hybrid HFS+ namespace. */
     322    RTFSISOMAKERNAMESPACE   Hfs;
    299323
    300324    /** The list of objects (RTFSISOMAKEROBJ). */
     
    331355    /** Namespace name for debugging purposes. */
    332356    const char     *pszName;
    333 } g_aRTFsIosNamespaces[] =
     357} g_aRTFsIsoNamespaces[] =
    334358{
    335359    {   RTFSISOMAKERNAMESPACE_ISO_9660, RT_OFFSETOF(RTFSISOMAKERINT, pPrimaryIsoRoot), RT_OFFSETOF(RTFSISOMAKEROBJ, pPrimaryName), "iso-9660" },
     
    339363};
    340364
    341 
    342 /**
    343  * Creates an ISO creator instance.
     365/**
     366 * Translates a single namespace flag (RTFSISOMAKERNAMESPACE_XXX) to an
     367 * index into g_aRTFsIsoNamespaces.
     368 */
     369static const uint8_t g_aidxRTFsIsoNamespaceFlagToIdx[] =
     370{
     371    /*[0]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     372    /*[RTFSISOMAKERNAMESPACE_ISO_9660] = */ 0,
     373    /*[2]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     374    /*[3]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     375    /*[RTFSISOMAKERNAMESPACE_JOLIET]   = */ 1,
     376    /*[5]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     377    /*[6]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     378    /*[7]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     379    /*[RTFSISOMAKERNAMESPACE_UDF]      = */ 2,
     380    /*[9]                              = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     381    /*[10]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     382    /*[11]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     383    /*[12]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     384    /*[13]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     385    /*[14]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     386    /*[15]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     387    /*[RTFSISOMAKERNAMESPACE_HFS]      = */ 3,
     388    /*[17]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     389    /*[18]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     390    /*[19]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     391    /*[20]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     392    /*[21]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     393    /*[22]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     394    /*[23]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     395    /*[24]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     396    /*[25]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     397    /*[26]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     398    /*[27]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     399    /*[28]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     400    /*[29]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     401    /*[30]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     402    /*[31]                             = */ RT_ELEMENTS(g_aRTFsIsoNamespaces),
     403};
     404
     405
     406/*********************************************************************************************************************************
     407*   Internal Functions                                                                                                           *
     408*********************************************************************************************************************************/
     409static int rtFsIsoMakerAddUnnamedDirWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKERDIR *ppDir);
     410
     411RTDECL(int) RTFsIsoMakerObjSetPath(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t fNamespaces, const char *pszPath);
     412
     413
     414/**
     415 * Creates an ISO maker instance.
    344416 *
    345417 * @returns IPRT status code.
     
    348420RTDECL(int) RTFsIsoMakerCreate(PRTFSISOMAKER phIsoMaker)
    349421{
     422    /*
     423     * Do some integrity checks first.
     424     */
     425    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_ISO_9660]].fNamespace == RTFSISOMAKERNAMESPACE_ISO_9660,
     426                 VERR_INTERNAL_ERROR_5);
     427    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_JOLIET]].fNamespace   == RTFSISOMAKERNAMESPACE_JOLIET,
     428                 VERR_INTERNAL_ERROR_5);
     429    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_UDF]].fNamespace      == RTFSISOMAKERNAMESPACE_UDF,
     430                 VERR_INTERNAL_ERROR_5);
     431    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKERNAMESPACE_HFS]].fNamespace      == RTFSISOMAKERNAMESPACE_HFS,
     432                 VERR_INTERNAL_ERROR_5);
     433
     434    /*
     435     * Create the instance with defaults.
     436     */
    350437    PRTFSISOMAKERINT pThis = (PRTFSISOMAKERINT)RTMemAllocZ(sizeof(*pThis));
    351438    if (pThis)
    352439    {
    353         pThis->uMagic                   = RTFSISOMAKERINT_MAGIC;
    354         pThis->cRefs                    = 1;
    355         //pThis->fSeenContent             = false;
    356         pThis->uIsoLevel                = 3;
    357         pThis->uRockRidgeLevel          = 1;
    358         pThis->uJolietLevel             = 3;
    359         //pThis->uJolietRockRidgeLevel    = 0;
     440        pThis->uMagic                       = RTFSISOMAKERINT_MAGIC;
     441        pThis->cRefs                        = 1;
     442        //pThis->fSeenContent               = false;
     443
     444        pThis->PrimaryIso.fNamespace        = RTFSISOMAKERNAMESPACE_ISO_9660;
     445        pThis->PrimaryIso.uLevel            = 3; /* 30 char names, large files */
     446        pThis->PrimaryIso.uRockRidgeLevel   = 1;
     447        pThis->Joliet.fNamespace            = RTFSISOMAKERNAMESPACE_JOLIET;
     448        pThis->Joliet.uLevel                = 3;
     449        //pThis->Joliet.uRockRidgeLevel     = 0;
     450        pThis->Udf.fNamespace               = RTFSISOMAKERNAMESPACE_UDF;
     451        //pThis->Udf.uLevel                 = 0;
     452        //pThis->Udf.uRockRidgeLevel        = 0;
     453        pThis->Hfs.fNamespace               = RTFSISOMAKERNAMESPACE_HFS;
     454        //pThis->Hfs.uLevel                 = 0;
     455        //pThis->Hfs.uRockRidgeLevel        = 0;
     456
    360457        RTListInit(&pThis->ObjectHead);
    361         pThis->cbTotal                  = _32K /* The system area size. */
    362                                         + RTFSISOMAKER_SECTOR_SIZE /* Primary volume descriptor. */
    363                                         + RTFSISOMAKER_SECTOR_SIZE /* Secondary volume descriptor for joliet. */
    364                                         + RTFSISOMAKER_SECTOR_SIZE /* Terminator descriptor. */;
     458        //pThis->cObjects                   = 0;
     459        //pThis->cNames                     = 0;
     460        //pThis->cbData                     = 0;
     461        pThis->cbTotal                      = _32K /* The system area size. */
     462                                            + RTFSISOMAKER_SECTOR_SIZE /* Primary volume descriptor. */
     463                                            + RTFSISOMAKER_SECTOR_SIZE /* Secondary volume descriptor for joliet. */
     464                                            + RTFSISOMAKER_SECTOR_SIZE /* Terminator descriptor. */;
    365465        *phIsoMaker = pThis;
    366466        return VINF_SUCCESS;
     
    564664
    565665
     666
    566667/*
    567668 *
    568  * Object level config
    569  * Object level config
    570  * Object level config
    571  *
    572  */
    573 
    574 
    575 /**
    576  * Translates an object index number to an object pointer, slow path.
    577  *
    578  * @returns Pointer to object, NULL if not found.
    579  * @param   pThis               The ISO creator instance.
    580  * @param   idxObj              The object index too resolve.
    581  */
    582 DECL_NO_INLINE(static, PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObjSlow(PRTFSISOMAKERINT pThis, uint32_t idxObj)
    583 {
    584     PRTFSISOMAKEROBJ pObj;
    585     RTListForEachReverse(&pThis->ObjectHead, pObj, RTFSISOMAKEROBJ, Entry)
    586     {
    587         if (pObj->idxObj == idxObj)
    588             return pObj;
    589     }
    590     return NULL;
    591 }
    592 
    593 
    594 /**
    595  * Translates an object index number to an object pointer.
    596  *
    597  * @returns Pointer to object, NULL if not found.
    598  * @param   pThis               The ISO creator instance.
    599  * @param   idxObj              The object index too resolve.
    600  */
    601 DECLINLINE(PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj)
    602 {
    603     PRTFSISOMAKEROBJ pObj = RTListGetLast(&pThis->ObjectHead, RTFSISOMAKEROBJ, Entry);
    604     if (!pObj || RT_LIKELY(pObj->idxObj == idxObj))
    605         return pObj;
    606     return rtFsIsoMakerIndexToObjSlow(pThis, idxObj);
     669 * Name space related internals.
     670 * Name space related internals.
     671 * Name space related internals.
     672 *
     673 */
     674
     675
     676/**
     677 * Gets the pointer to the root member for the given namespace.
     678 *
     679 * @returns Pointer to root pointer.
     680 * @param   pThis               The ISO maker instance.
     681 * @param   fNamespace          The namespace which name to find.
     682 */
     683static PPRTFSISOMAKERNAME rtFsIsoMakerGetRootForNamespace(PRTFSISOMAKERINT pThis, uint32_t fNamespace)
     684{
     685    Assert(RT_IS_POWER_OF_TWO(fNamespace));
     686    Assert(fNamespace);
     687    Assert(fNamespace <= RTFSISOMAKERNAMESPACE_HFS);
     688    return (PPRTFSISOMAKERNAME)((uintptr_t)pThis + g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[fNamespace]].offRoot);
     689}
     690
     691
     692/**
     693 * Gets the pointer to the name member for the given namespace.
     694 *
     695 * @returns Pointer to name member.
     696 * @param   pObj                The object to find a name member in.
     697 * @param   fNamespace          The namespace which name to find.
     698 */
     699static PPRTFSISOMAKERNAME rtFsIsoMakerObjGetNameForNamespace(PRTFSISOMAKEROBJ pObj, uint32_t fNamespace)
     700{
     701    Assert(RT_IS_POWER_OF_TWO(fNamespace));
     702    Assert(fNamespace);
     703    Assert(fNamespace <= RTFSISOMAKERNAMESPACE_HFS);
     704    return (PPRTFSISOMAKERNAME)((uintptr_t)pObj + g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[fNamespace]].offName);
    607705}
    608706
     
    637735
    638736/**
    639  * Locates a child object by its specified name.
     737 * Locates a child entry by its specified name.
    640738 *
    641739 * @returns Pointer to the child if found, NULL if not.
    642  * @param   pDirObj             The directory object to search.
     740 * @param   pDirName            The directory name to search.
    643741 * @param   pszEntry            The (specified) entry name.
    644742 * @param   cchEntry            The length of the name.
    645743 */
    646 static PRTFSISOMAKERNAME rtFsIsoMakerFindObjInDirBySpec(PRTFSISOMAKERNAME pDirObj, const char *pszEntry, size_t cchEntry)
    647 {
    648     if (pDirObj)
    649     {
    650         PRTFSISOMAKERNAMEDIR pDir = pDirObj->pDir;
     744static PRTFSISOMAKERNAME rtFsIsoMakerFindEntryInDirBySpec(PRTFSISOMAKERNAME pDirName, const char *pszEntry, size_t cchEntry)
     745{
     746    if (pDirName)
     747    {
     748        PRTFSISOMAKERNAMEDIR pDir = pDirName->pDir;
    651749        AssertReturn(pDir, NULL);
    652750
     
    663761}
    664762
     763
     764/**
     765 * Locates a subdir object in any namespace by its specified name.
     766 *
     767 * This is used to avoid having one instance of RTFSISOMAKERDIR in each
     768 * namespace for the same directory.
     769 *
     770 * @returns Pointer to the subdir object if found, NULL if not.
     771 * @param   pDirObj             The directory object to search.
     772 * @param   pszEntry            The (specified) entry name.
     773 * @param   cchEntry            The length of the name.
     774 * @param   fSkipNamespaces     Namespaces to skip.
     775 * @sa      rtFsIsoMakerFindEntryInDirBySpec
     776 */
     777static PRTFSISOMAKERDIR rtFsIsoMakerFindSubdirBySpec(PRTFSISOMAKERDIR pDirObj, const char *pszEntry, size_t cchEntry,
     778                                                     uint32_t fSkipNamespaces)
     779{
     780    AssertReturn(pDirObj, NULL);
     781    AssertReturn(pDirObj->Core.enmType == RTFSISOMAKEROBJTYPE_DIR, NULL);
     782    for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIsoNamespaces); i++)
     783        if (!(fSkipNamespaces & g_aRTFsIsoNamespaces[i].fNamespace))
     784        {
     785            PRTFSISOMAKERNAME pDirName = *(PPRTFSISOMAKERNAME)((uintptr_t)pDirObj + g_aRTFsIsoNamespaces[i].offName);
     786            if (pDirName)
     787            {
     788                PRTFSISOMAKERNAMEDIR pDir = pDirName->pDir;
     789                AssertStmt(pDir, continue);
     790
     791                uint32_t i = pDir->cChildren;
     792                while (i-- > 0)
     793                {
     794                    PRTFSISOMAKERNAME pChild = pDir->papChildren[i];
     795                    if (   pChild->cchSpecNm == cchEntry
     796                        && pChild->pDir      != NULL
     797                        && RTStrNICmp(pChild->pszSpecNm, pszEntry, cchEntry) == 0)
     798                        return (PRTFSISOMAKERDIR)pChild->pObj;
     799                }
     800            }
     801        }
     802    return NULL;
     803}
     804
     805
    665806/**
    666807 * Copy and convert a name to valid ISO-9660 (d-characters only).
     
    670811 *
    671812 * @returns Length of the resulting string.
    672  * @param   pszDst              The output buffer.
    673  * @param   cchDstMax           The maximum number of (d-chars) to put in the
    674  *                              output buffer .
    675  * @param   pszSrc              The UTF-8 source string.
    676  * @param   cchSrc              The maximum number of chars to copy from the
    677  *                              source string.
    678  */
    679 static size_t rtFsIsoMakerCopyIso9660Name(char *pszDst, size_t cchDstMax, const char *pszSrc, size_t cchSrc)
    680 {
    681     const char *pszSrcIn = pszSrc;
     813 * @param   pszDst      The output buffer.
     814 * @param   cchDstMax   The maximum number of (d-chars) to put in the output
     815 *                      buffer.
     816 * @param   pchSrc      The UTF-8 source string (not neccessarily terminated).
     817 * @param   cchSrc      The maximum number of chars to copy from the source
     818 *                      string.
     819 */
     820static size_t rtFsIsoMakerCopyIso9660Name(char *pszDst, size_t cchDstMax, const char *pchSrc, size_t cchSrc)
     821{
     822    const char *pchSrcIn = pchSrc;
    682823    size_t      offDst = 0;
    683     while ((size_t)(pszSrc - pszSrcIn) < cchSrc)
     824    while ((size_t)(pchSrc - pchSrcIn) < cchSrc)
    684825    {
    685826        RTUNICP uc;
    686         int rc = RTStrGetCpEx(&pszSrc, &uc);
     827        int rc = RTStrGetCpEx(&pchSrc, &uc);
    687828        if (RT_SUCCESS(rc))
    688829        {
     
    702843
    703844/**
    704  * Normalizes a name for the specified name space.
     845 * Normalizes a name for the primary ISO-9660 namespace.
    705846 *
    706847 * @returns IPRT status code.
    707848 * @param   pThis       The ISO maker instance.
    708849 * @param   pParent     The parent directory.  NULL if root.
    709  * @param   pszSrc      The specified name to normalize.
    710  * @param   fNamespace  The namespace rulez to normalize it according to.
     850 * @param   pchSrc      The specified name to normalize (not necessarily zero
     851 *                      terminated).
     852 * @param   cchSrc      The length of the specified name.
    711853 * @param   fIsDir      Indicates whether it's a directory or file (like).
    712854 * @param   pszDst      The output buffer.  Must be at least 32 bytes.
     
    715857 *                      not counting the terminator).
    716858 */
    717 static int rtFsIsoMakerNormalizeNameForNamespace(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME pParent, const char *pszSrc,
    718                                                  uint32_t fNamespace, bool fIsDir, char *pszDst, size_t cbDst, size_t *pcchDst)
    719 {
    720     size_t cchSrc = strlen(pszSrc);
    721     if (cchSrc)
     859static int rtFsIsoMakerNormalizeNameForPrimaryIso9660(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME pParent,
     860                                                      const char *pchSrc, size_t cchSrc, bool fIsDir,
     861                                                      char *pszDst, size_t cbDst, size_t *pcchDst)
     862{
     863    AssertReturn(cbDst > ISO9660_MAX_NAME_LEN, VERR_INTERNAL_ERROR_3);
     864
     865    /* Skip leading dots. */
     866    while (cchSrc > 0 && *pchSrc == '.')
     867        pchSrc++, cchSrc--;
     868    if (!cchSrc)
     869    {
     870        pchSrc = "DOTS";
     871        cchSrc = 4;
     872    }
     873
     874    /*
     875     * Produce a first name.
     876     */
     877    size_t cchDst;
     878    size_t offDstDot;
     879    if (fIsDir)
     880        offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8,
     881                                                         pchSrc, cchSrc);
     882    else
     883    {
     884        /* Look for the last dot and try preserve the extension when doing the conversion. */
     885        size_t offLastDot = cchSrc;
     886        for (size_t off = 0; off < cchSrc; off++)
     887            if (pchSrc[off] == '.')
     888                offLastDot = off;
     889
     890        if (offLastDot == cchSrc)
     891            offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8,
     892                                                             pchSrc, cchSrc);
     893        else
     894        {
     895            const char * const pchSrcExt = &pchSrc[offLastDot + 1];
     896            size_t       const cchSrcExt = cchSrc - offLastDot - 1;
     897            if (pThis->uIsoLevel < 2)
     898            {
     899                cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, 8, pchSrc, cchSrc);
     900                offDstDot = cchDst;
     901                pszDst[cchDst++] = '.';
     902                cchDst += rtFsIsoMakerCopyIso9660Name(&pszDst[cchDst], 3, pchSrcExt, cchSrcExt);
     903            }
     904            else
     905            {
     906                size_t cchDstExt = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2, pchSrcExt, cchSrcExt);
     907                if (cchDstExt > 0)
     908                {
     909                    size_t cchBasename = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2,
     910                                                                     pchSrc, offLastDot);
     911                    if (cchBasename + 1 + cchDstExt <= ISO9660_MAX_NAME_LEN)
     912                        cchDst = cchBasename;
     913                    else
     914                        cchDst = ISO9660_MAX_NAME_LEN - 1 - RT_MIN(cchDstExt, 4);
     915                    offDstDot = cchDst;
     916                    pszDst[cchDst++] = '.';
     917                    cchDst += rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 1 - cchDst,
     918                                                          pchSrcExt, cchSrcExt);
     919                }
     920                else
     921                    offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN, pchSrc, cchSrc);
     922            }
     923        }
     924    }
     925
     926    /*
     927     * Unique name?
     928     */
     929    if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst))
     930    {
     931        *pcchDst = cchDst;
     932        return VINF_SUCCESS;
     933    }
     934
     935    /*
     936     * Mangle the name till we've got a unique one.
     937     */
     938    size_t const cchMaxBasename = (pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8) - (cchDst - offDstDot);
     939    size_t       cchInserted = 0;
     940    for (uint32_t i = 0; i < _32K; i++)
     941    {
     942        /* Add a numberic infix. */
     943        char szOrd[64];
     944        size_t cchOrd = RTStrFormatU32(szOrd, sizeof(szOrd), i + 1, 10, -1, -1, 0 /*fFlags*/);
     945        Assert((ssize_t)cchOrd > 0);
     946
     947        /* Do we need to shuffle the suffix? */
     948        if (cchOrd > cchInserted)
     949        {
     950            if (offDstDot < cchMaxBasename)
     951            {
     952                memmove(&pszDst[offDstDot + 1], &pszDst[offDstDot], cchDst + 1 - offDstDot);
     953                cchDst++;
     954                offDstDot++;
     955            }
     956            cchInserted = cchOrd;
     957        }
     958
     959        /* Insert the new infix and try again. */
     960        memcpy(&pszDst[offDstDot - cchOrd], szOrd, cchOrd);
     961        if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst))
     962        {
     963            *pcchDst = cchDst;
     964            return VINF_SUCCESS;
     965        }
     966    }
     967    AssertFailed();
     968    return VERR_DUPLICATE;
     969}
     970
     971
     972/**
     973 * Normalizes a name for the specified name space.
     974 *
     975 * @returns IPRT status code.
     976 * @param   pThis       The ISO maker instance.
     977 * @param   pParent     The parent directory.  NULL if root.
     978 * @param   pchSrc      The specified name to normalize (not necessarily zero
     979 *                      terminated).
     980 * @param   cchSrc      The length of the specified name.
     981 * @param   fNamespace  The namespace rules to normalize it according to.
     982 * @param   fIsDir      Indicates whether it's a directory or file (like).
     983 * @param   pszDst      The output buffer.  Must be at least 32 bytes.
     984 * @param   cbDst       The size of the output buffer.
     985 * @param   pcchDst     Where to return the length of the returned string (i.e.
     986 *                      not counting the terminator).
     987 */
     988static int rtFsIsoMakerNormalizeNameForNamespace(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME pParent,
     989                                                 const char *pchSrc, size_t cchSrc, uint32_t fNamespace, bool fIsDir,
     990                                                 char *pszDst, size_t cbDst, size_t *pcchDst)
     991{
     992    if (cchSrc > 0)
    722993    {
    723994        /*
    724995         * Check that the object doesn't already exist.
    725996         */
    726         AssertReturn(!rtFsIsoMakerFindObjInDirBySpec(pParent, pszSrc, cchSrc), VERR_ALREADY_EXISTS);
     997        AssertReturn(!rtFsIsoMakerFindEntryInDirBySpec(pParent, pchSrc, cchSrc), VERR_ALREADY_EXISTS);
    727998        switch (fNamespace)
    728999        {
    7291000            /*
    730              * This one is fun. :)
     1001             * This one is a lot of work, so separate function.
    7311002             */
    7321003            case RTFSISOMAKERNAMESPACE_ISO_9660:
    733             {
    734                 AssertReturn(cbDst > ISO9660_MAX_NAME_LEN, VERR_INTERNAL_ERROR_3);
    735 
    736                 /* Skip leading dots. */
    737                 while (*pszSrc == '.')
    738                     pszSrc++, cchSrc--;
    739                 if (!cchSrc)
    740                 {
    741                     pszSrc = "DOTS";
    742                     cchSrc = 4;
    743                 }
    744 
    745                 /*
    746                  * Produce a first name.
    747                  */
    748                 size_t cchDst;
    749                 size_t offDstDot;
    750                 if (fIsDir)
    751                     offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8,
    752                                                                      pszSrc, cchSrc);
    753                 else
    754                 {
    755                     /* Look for the last dot and try preserve the extension when doing the conversion. */
    756                     size_t offLastDot = cchSrc;
    757                     for (size_t off = 0; off < cchSrc; off++)
    758                         if (pszSrc[off] == '.')
    759                             offLastDot = off;
    760 
    761                     if (offLastDot == cchSrc)
    762                         offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8,
    763                                                                          pszSrc, cchSrc);
    764                     else
    765                     {
    766                         const char * const pszSrcExt = &pszSrc[offLastDot + 1];
    767                         size_t       const cchSrcExt = cchSrc - offLastDot - 1;
    768                         if (pThis->uIsoLevel < 2)
    769                         {
    770                             cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, 8, pszSrc, cchSrc);
    771                             offDstDot = cchDst;
    772                             pszDst[cchDst++] = '.';
    773                             cchDst += rtFsIsoMakerCopyIso9660Name(&pszDst[cchDst], 3, pszSrcExt, cchSrcExt);
    774                         }
    775                         else
    776                         {
    777                             size_t cchDstExt = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2, pszSrcExt, cchSrcExt);
    778                             if (cchDstExt > 0)
    779                             {
    780                                 size_t cchBasename = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 2,
    781                                                                                  pszSrc, offLastDot);
    782                                 if (cchBasename + 1 + cchDstExt <= ISO9660_MAX_NAME_LEN)
    783                                     cchDst = cchBasename;
    784                                 else
    785                                     cchDst = ISO9660_MAX_NAME_LEN - 1 - RT_MIN(cchDstExt, 4);
    786                                 offDstDot = cchDst;
    787                                 pszDst[cchDst++] = '.';
    788                                 cchDst += rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN - 1 - cchDst,
    789                                                                       pszSrcExt, cchSrcExt);
    790                             }
    791                             else
    792                                 offDstDot = cchDst = rtFsIsoMakerCopyIso9660Name(pszDst, ISO9660_MAX_NAME_LEN, pszSrc, cchSrc);
    793                         }
    794                     }
    795                 }
    796 
    797                 /*
    798                  * Unique name?
    799                  */
    800                 if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst))
    801                 {
    802                     *pcchDst = cchDst;
    803                     return VINF_SUCCESS;
    804                 }
    805 
    806                 /*
    807                  * Mangle the name till we've got a unique one.
    808                  */
    809                 size_t const cchMaxBasename = (pThis->uIsoLevel >= 2 ? ISO9660_MAX_NAME_LEN : 8) - (cchDst - offDstDot);
    810                 size_t       cchInserted = 0;
    811                 for (uint32_t i = 0; i < _32K; i++)
    812                 {
    813                     /* Add a numberic infix. */
    814                     char szOrd[64];
    815                     size_t cchOrd = RTStrFormatU32(szOrd, sizeof(szOrd), i + 1, 10, -1, -1, 0 /*fFlags*/);
    816                     Assert((ssize_t)cchOrd > 0);
    817 
    818                     /* Do we need to shuffle the suffix? */
    819                     if (cchOrd > cchInserted)
    820                     {
    821                         if (offDstDot < cchMaxBasename)
    822                         {
    823                             memmove(&pszDst[offDstDot + 1], &pszDst[offDstDot], cchDst + 1 - offDstDot);
    824                             cchDst++;
    825                             offDstDot++;
    826                         }
    827                         cchInserted = cchOrd;
    828                     }
    829 
    830                     /* Insert the new infix and try again. */
    831                     memcpy(&pszDst[offDstDot - cchOrd], szOrd, cchOrd);
    832                     if (!rtFsIsoMakerFindObjInDir(pParent, pszDst, cchDst))
    833                     {
    834                         *pcchDst = cchDst;
    835                         return VINF_SUCCESS;
    836                     }
    837                 }
    838                 AssertFailed();
    839                 return VERR_DUPLICATE;
    840             }
     1004                return rtFsIsoMakerNormalizeNameForPrimaryIso9660(pThis, pParent, pchSrc, cchSrc, fIsDir, pszDst, cbDst, pcchDst);
    8411005
    8421006            /*
     
    8451009            case RTFSISOMAKERNAMESPACE_JOLIET:
    8461010            {
     1011/** @todo Joliet name limit.   */
    8471012                AssertReturn(cbDst > cchSrc, VERR_BUFFER_OVERFLOW);
    848                 memcpy(pszDst, pszSrc, cchSrc);
     1013                memcpy(pszDst, pchSrc, cchSrc);
    8491014                pszDst[cchSrc] = '\0';
    8501015                *pcchDst = cchSrc;
     
    8731038
    8741039
    875 static int rtFsIsoMakerPathToParent(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAME *ppRoot, uint32_t fNamespace, const char *pszPath,
    876                                     PRTFSISOMAKERNAME *ppParent, const char **ppszEntry)
    877 {
    878     RT_NOREF(pThis, ppRoot, fNamespace, pszPath, ppParent, ppszEntry);
    879     return -1;
    880 }
    881 
    882 
    883 static int rtFsIsoMakerObjSetPathInOne(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pEntry, uint32_t fNamespace, const char *pszPath,
    884                                        PRTFSISOMAKERNAME *ppRoot, PRTFSISOMAKERNAME *ppName)
     1040/**
     1041 * Sets the name of an object in a namespace.
     1042 *
     1043 * The object cannot currently have a name in that namespace.
     1044 *
     1045 * @returns IPRT status code.
     1046 * @param   pThis       The ISO maker instance.
     1047 * @param   pNamespace  The namespace.
     1048 * @param   pObj        The object to name.
     1049 * @param   ppName      The pointer to the object's namespace member.
     1050 * @param   pParent     The parent namespace entry
     1051 * @param   pchSpec     The specified name (not necessarily terminated).
     1052 * @param   cchSpec     The specified name length.
     1053 * @param   ppNewName   Where to return the name entry.  Optional.
     1054 */
     1055static int rtFsIsoMakerObjSetName(PRTFSISOMAKERINT pThis, PRTFSISOMAKERNAMESPACE pNamespace, PRTFSISOMAKEROBJ pObj,
     1056                                  PPRTFSISOMAKERNAME ppName, PRTFSISOMAKERNAME pParent, const char *pchSpec, size_t cchSpec,
     1057                                  PPRTFSISOMAKERNAME ppNewName)
     1058{
     1059    Assert(cchSpec < _32K);
     1060
     1061    /*
     1062     * To avoid need to revert anything, make sure papChildren in the parent is
     1063     * large enough.  If root object, make sure we haven't got a root already.
     1064     */
     1065    PPRTFSISOMAKERNAME ppRoot;
     1066    if (pParent)
     1067    {
     1068        AssertReturn(pParent->pDir, VERR_INTERNAL_ERROR_5);
     1069        uint32_t cChildren = pParent->pDir->cChildren;
     1070        if (cChildren & 31)
     1071        { /* likely */ }
     1072        else
     1073        {
     1074            AssertReturn(cChildren < RTFSISOMAKER_MAX_OBJECTS_PER_DIR, VERR_TOO_MUCH_DATA);
     1075            void *pvNew = RTMemRealloc(pParent->pDir->papChildren, (cChildren + 32) * sizeof(pParent->pDir->papChildren[0]));
     1076            AssertReturn(pvNew, VERR_NO_MEMORY);
     1077            pParent->pDir->papChildren = (PPRTFSISOMAKERNAME)pvNew;
     1078        }
     1079        ppRoot = NULL;
     1080    }
     1081    else
     1082    {
     1083        ppRoot = rtFsIsoMakerGetRootForNamespace(pThis, fNamespace);
     1084        AssertReturn(*ppRoot, VERR_INTERNAL_ERROR_5);
     1085    }
     1086
     1087    /*
     1088     * Normalize the name for this namespace.
     1089     */
     1090    size_t cchName;
     1091    char   szName[RTFSISOMAKER_MAX_NAME_BUF];
     1092    int rc = rtFsIsoMakerNormalizeNameForNamespace(pThis, pParent, pchSpec, cchSpec, fNamespace,
     1093                                                   pObj->enmType == RTFSISOMAKEROBJTYPE_DIR,
     1094                                                   szName, sizeof(szName), &cchName);
     1095    if (RT_SUCCESS(rc))
     1096    {
     1097        size_t cbName = sizeof(RTFSISOMAKERNAME)
     1098                      + cchName + 1
     1099                      + cchSpec + 1;
     1100        if (pObj->enmType == RTFSISOMAKEROBJTYPE_DIR)
     1101            cbName = RT_ALIGN_Z(cbName, 8) + sizeof(RTFSISOMAKERNAMEDIR);
     1102        PRTFSISOMAKERNAME pName = (PRTFSISOMAKERNAME)RTMemAllocZ(cbName);
     1103        if (pName)
     1104        {
     1105            pName->pObj                 = pObj;
     1106            pName->pParent              = pParent;
     1107            pName->cchName              = (uint16_t)cchName;
     1108
     1109            char *pszDst = &pName->szName[cchName + 1];
     1110            memcpy(pszDst, pchSpec, cchSpec);
     1111            pszDst[cchSpec] = '\0';
     1112            pName->pszSpecNm            = pszDst;
     1113            pName->pszRockRidgeNm       = pszDst;
     1114            pName->pszTransNm           = pszDst;
     1115            pName->cchSpecNm            = (uint16_t)cchSpec;
     1116            pName->cchRockRidgeNm       = 0;
     1117            pName->cchTransNm           = 0;
     1118            pName->uDepth               = pParent->uDepth + 1;
     1119            pName->fRockRidgeNmAlloced  = false;
     1120            pName->fTransNmAlloced      = false;
     1121
     1122            memcpy(pName->szName, szName, cchName);
     1123            pName->szName[cchName] = '\0';
     1124
     1125            if (pObj->enmType != RTFSISOMAKEROBJTYPE_DIR)
     1126                pName->pDir             = NULL;
     1127            else
     1128            {
     1129                size_t offDir = RT_UOFFSETOF(RTFSISOMAKERNAME, szName) + cchName + 1 + cchSpec + 1;
     1130                offDir = RT_ALIGN_Z(offDir, 8);
     1131                PRTFSISOMAKERNAMEDIR pDir = (PRTFSISOMAKERNAMEDIR)((uintptr_t)pName + offDir);
     1132                pDir->offDir        = UINT64_MAX;
     1133                pDir->cbDir         = 0;
     1134                pDir->cChildren     = 0;
     1135                pDir->papChildren   = NULL;
     1136                pDir->pTransTblFile = NULL;
     1137                /** @todo TRANS.TBL files. */
     1138
     1139                pName->pDir = pDir;
     1140            }
     1141
     1142            /*
     1143             * Do the linking and stats.
     1144             */
     1145            if (pParent)
     1146                pParent->pDir->papChildren[pParent->pDir->cChildren++] = pName;
     1147            else
     1148                *ppRoot = pName;
     1149            *ppName = pName;
     1150            pThis->cNames++;
     1151
     1152            /*
     1153             * Done.
     1154             */
     1155            if (ppNewName)
     1156                *ppNewName = pName;
     1157            return VINF_SUCCESS;
     1158        }
     1159    }
     1160    return rc;
     1161}
     1162
     1163
     1164static int rtFsIsoMakerPathToParent(PRTFSISOMAKERINT pThis, PPRTFSISOMAKERNAME ppRoot, uint32_t fNamespace, const char *pszPath,
     1165                                    PPRTFSISOMAKERNAME ppParent, const char **ppszEntry, size_t *pcchEntry)
     1166{
     1167    int rc;
     1168    AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INTERNAL_ERROR_4);
     1169
     1170    /*
     1171     * Deal with the special case of the root.
     1172     */
     1173    while (RTPATH_IS_SLASH(*pszPath))
     1174        pszPath++;
     1175    AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4);
     1176
     1177    PRTFSISOMAKERNAME pParent = *ppRoot;
     1178    if (!pParent)
     1179    {
     1180        PRTFSISOMAKERDIR pDir;
     1181        if (pThis->cObjects == 0)
     1182        {
     1183            rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pDir);
     1184            AssertRCReturn(rc, rc);
     1185        }
     1186        else
     1187        {
     1188            pDir = RTListGetFirst(&pThis->ObjectHead, RTFSISOMAKERDIR, Core.Entry);
     1189#ifdef RT_STRICT
     1190            Assert(pDir);
     1191            Assert(pDir->Core.idxObj == 0);
     1192            Assert(pDir->Core.enmType == RTFSISOMAKEROBJTYPE_DIR);
     1193            Assert(*rtFsIsoMakerObjGetNameForNamespace(&pDir->Core, fNamespace) == NULL);
     1194#endif
     1195        }
     1196
     1197        rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pDir->Core, rtFsIsoMakerObjGetNameForNamespace(&pDir->Core, fNamespace),
     1198                                    NULL /*pParent*/, "", 0, &pParent);
     1199        AssertRCReturn(rc, rc);
     1200        AssertReturn(*ppRoot, VERR_INTERNAL_ERROR_4);
     1201        pParent = *ppRoot;
     1202    }
     1203
     1204    /*
     1205     * Now, do the rest of the path.
     1206     */
     1207    for (;;)
     1208    {
     1209        /*
     1210         * Find the end of the component and see if its the final one or not.
     1211         */
     1212        char ch;
     1213        size_t cchComponent = 0;
     1214        while ((ch = pszPath[cchComponent]) != '\0' && RTPATH_IS_SLASH(ch))
     1215            cchComponent++;
     1216        AssertReturn(cchComponent > 0, VERR_INTERNAL_ERROR_4);
     1217
     1218        size_t offNext = cchComponent;
     1219        while (RTPATH_IS_SLASH(ch))
     1220            ch = pszPath[offNext++];
     1221
     1222        if (ch == '\0')
     1223        {
     1224            /*
     1225             * Final component.  Make sure it is not dot or dot-dot before returning.
     1226             */
     1227            AssertReturn(   pszPath[0] != '.'
     1228                         || cchComponent > 2
     1229                         || (   cchComponent == 2
     1230                             && pszPath[1] != '.'),
     1231                         VERR_INVALID_NAME);
     1232
     1233            *ppParent  = pParent;
     1234            *ppszEntry = pszPath;
     1235            *pcchEntry = cchComponent;
     1236            return VINF_SUCCESS;
     1237        }
     1238
     1239        /*
     1240         * Deal with dot and dot-dot.
     1241         */
     1242        if (cchComponent == 1 && pszPath[0] == '.')
     1243        { /* nothing to do */ }
     1244        else if (cchComponent == 2 && pszPath[0] == '.' && pszPath[1] == '.')
     1245        {
     1246            if (pParent->pParent)
     1247                pParent = pParent->pParent;
     1248        }
     1249        else
     1250        {
     1251            /*
     1252             * Look it up.
     1253             */
     1254            PRTFSISOMAKERNAME pChild = rtFsIsoMakerFindEntryInDirBySpec(pParent, pszPath, cchComponent);
     1255            if (pChild)
     1256                pParent = pChild;
     1257            else
     1258            {
     1259                /* Try see if we've got a directory with the same spec name in a different namespace.
     1260                   (We don't want to waste heap by creating a directory instance per namespace.) */
     1261                PRTFSISOMAKERDIR pChildObj = rtFsIsoMakerFindSubdirBySpec((PRTFSISOMAKERDIR)pParent->pObj,
     1262                                                                           pszPath, cchComponent, fNamespace);
     1263                if (pChildObj)
     1264                {
     1265                    PPRTFSISOMAKERNAME ppChildName = rtFsIsoMakerObjGetNameForNamespace(&pChildObj->Core, fNamespace);
     1266                    if (!*ppChildName)
     1267                    {
     1268                        rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pChildObj->Core, ppChildName, pParent,
     1269                                                    pszPath, cchComponent, &pChild);
     1270                        if (RT_FAILURE(rc))
     1271                            return rc;
     1272                        AssertReturn(pChild != NULL, VERR_INTERNAL_ERROR_4);
     1273                    }
     1274                }
     1275                /* If we didn't have luck in other namespaces, create a new directory. */
     1276                if (!pChild)
     1277                {
     1278                    rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pChildObj);
     1279                    if (RT_SUCCESS(rc))
     1280                        rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pChildObj->Core,
     1281                                                    rtFsIsoMakerObjGetNameForNamespace(&pChildObj->Core, fNamespace),
     1282                                                    pParent, pszPath, cchComponent, &pChild);
     1283                    if (RT_FAILURE(rc))
     1284                        return rc;
     1285                    AssertReturn(pChild != NULL, VERR_INTERNAL_ERROR_4);
     1286                }
     1287            }
     1288        }
     1289
     1290        /*
     1291         * Skip ahead in the path.
     1292         */
     1293        pszPath += offNext;
     1294    }
     1295}
     1296
     1297
     1298/**
     1299 * Worker for RTFsIsoMakerObjSetPath that operates on a single namespace.
     1300 *
     1301 * @returns IPRT status code.
     1302 * @param   pThis           The ISO maker instance.
     1303 * @param   pObj            The filesystem object to name.
     1304 * @param   fNamespace      The namespace to name it in.
     1305 * @param   pszPath         The path to the entry in the namespace.
     1306 * @param   ppRoot          The namespace root.
     1307 * @param   ppName          The namespace name member in @a paEntry.
     1308 */
     1309static int rtFsIsoMakerObjSetPathInOne(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj, uint32_t fNamespace, const char *pszPath,
     1310                                       PPRTFSISOMAKERNAME ppRoot, PPRTFSISOMAKERNAME ppName)
    8851311{
    8861312    AssertReturn(!*ppName, VERR_WRONG_ORDER);
     1313    AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INTERNAL_ERROR_5);
    8871314
    8881315    /*
     
    8921319    PRTFSISOMAKERNAME   pParent;
    8931320    const char         *pszEntry;
     1321    size_t              cchEntry;
    8941322    int                 rc;
    8951323    if (pszPath[1] != '\0')
    896         rc = rtFsIsoMakerPathToParent(pThis, ppRoot, fNamespace, pszPath, &pParent, &pszEntry);
     1324        rc = rtFsIsoMakerPathToParent(pThis, ppRoot, fNamespace, pszPath, &pParent, &pszEntry, &cchEntry);
    8971325    else
    8981326    {
     
    9001328         * Special case for the root directory.
    9011329         */
     1330        Assert(pObj->enmType == RTFSISOMAKEROBJTYPE_DIR);
    9021331        AssertReturn(!*ppRoot, VERR_WRONG_ORDER);
    903         pszEntry = &pszPath[1];
    904         pParent = NULL;
    905         rc = VINF_SUCCESS;
    906         Assert(pEntry->enmType == RTFSISOMAKEROBJTYPE_DIR);
    907     }
     1332        pszEntry = "/";
     1333        cchEntry = 0;
     1334        pParent  = NULL;
     1335        rc       = VINF_SUCCESS;
     1336    }
     1337
     1338    /*
     1339     * Do the job on the final path component.
     1340     */
    9081341    if (RT_SUCCESS(rc))
    9091342    {
    910         /*
    911          * .
    912          */
    913         //size_t cchEntry = strlen(pszEntry);
    914         size_t cchName;
    915         char   szName[RTFSISOMAKER_MAX_NAME_BUF];
    916         rc = rtFsIsoMakerNormalizeNameForNamespace(pThis, pParent, pszEntry, fNamespace,
    917                                                    pEntry->enmType == RTFSISOMAKEROBJTYPE_DIR, szName, sizeof(szName), &cchName);
    918         if (RT_SUCCESS(rc))
    919         {
    920 
    921             //PRTFSISOMAKERNAME pNameEntry = RTMemAllocZ()
    922         }
    923     }
    924 
     1343        AssertReturn(!RTPATH_IS_SLASH(pszEntry[cchEntry]) || pObj->enmType == RTFSISOMAKEROBJTYPE_DIR,
     1344                     VERR_NOT_A_DIRECTORY);
     1345        rc = rtFsIsoMakerObjSetName(pThis, pNamespace, pObj, ppName, pParent, pszEntry, cchEntry, NULL);
     1346    }
    9251347    return rc;
     1348}
     1349
     1350
     1351
     1352/*
     1353 *
     1354 * Object level config
     1355 * Object level config
     1356 * Object level config
     1357 *
     1358 */
     1359
     1360
     1361/**
     1362 * Translates an object index number to an object pointer, slow path.
     1363 *
     1364 * @returns Pointer to object, NULL if not found.
     1365 * @param   pThis               The ISO maker instance.
     1366 * @param   idxObj              The object index too resolve.
     1367 */
     1368DECL_NO_INLINE(static, PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObjSlow(PRTFSISOMAKERINT pThis, uint32_t idxObj)
     1369{
     1370    PRTFSISOMAKEROBJ pObj;
     1371    RTListForEachReverse(&pThis->ObjectHead, pObj, RTFSISOMAKEROBJ, Entry)
     1372    {
     1373        if (pObj->idxObj == idxObj)
     1374            return pObj;
     1375    }
     1376    return NULL;
     1377}
     1378
     1379
     1380/**
     1381 * Translates an object index number to an object pointer.
     1382 *
     1383 * @returns Pointer to object, NULL if not found.
     1384 * @param   pThis               The ISO maker instance.
     1385 * @param   idxObj              The object index too resolve.
     1386 */
     1387DECLINLINE(PRTFSISOMAKEROBJ) rtFsIsoMakerIndexToObj(PRTFSISOMAKERINT pThis, uint32_t idxObj)
     1388{
     1389    PRTFSISOMAKEROBJ pObj = RTListGetLast(&pThis->ObjectHead, RTFSISOMAKEROBJ, Entry);
     1390    if (!pObj || RT_LIKELY(pObj->idxObj == idxObj))
     1391        return pObj;
     1392    return rtFsIsoMakerIndexToObjSlow(pThis, idxObj);
    9261393}
    9271394
     
    9591426     */
    9601427    int rc = VINF_SUCCESS;
    961     for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIosNamespaces); i++)
    962         if (fNamespaces & g_aRTFsIosNamespaces[i].fNamespace)
    963         {
    964             int rc2 = rtFsIsoMakerObjSetPathInOne(pThis, pObj, g_aRTFsIosNamespaces[i].fNamespace, pszPath,
    965                                                   (PRTFSISOMAKERNAME *)((uintptr_t)pThis + g_aRTFsIosNamespaces[i].offRoot),
    966                                                   (PRTFSISOMAKERNAME *)((uintptr_t)pObj  + g_aRTFsIosNamespaces[i].offName));
     1428    for (uint32_t i = 0; i < RT_ELEMENTS(g_aRTFsIsoNamespaces); i++)
     1429        if (fNamespaces & g_aRTFsIsoNamespaces[i].fNamespace)
     1430        {
     1431            int rc2 = rtFsIsoMakerObjSetPathInOne(pThis, pObj, g_aRTFsIsoNamespaces[i].fNamespace, pszPath,
     1432                                                  (PPRTFSISOMAKERNAME)((uintptr_t)pThis + g_aRTFsIsoNamespaces[i].offRoot),
     1433                                                  (PPRTFSISOMAKERNAME)((uintptr_t)pObj  + g_aRTFsIsoNamespaces[i].offName));
    9671434            if (RT_SUCCESS(rc2) || RT_FAILURE(rc))
    9681435                continue;
     
    9971464
    9981465/**
     1466 * Internal function for adding an unnamed directory.
     1467 *
     1468 * @returns IPRT status code.
     1469 * @param   pThis               The ISO make instance.
     1470 * @param   ppDir               Where to return the directory.
     1471 */
     1472static int rtFsIsoMakerAddUnnamedDirWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKERDIR *ppDir)
     1473{
     1474    PRTFSISOMAKERDIR pDir = (PRTFSISOMAKERDIR)RTMemAllocZ(sizeof(*pDir));
     1475    AssertReturn(pDir, VERR_NO_MEMORY);
     1476    int rc = rtFsIsoMakerInitCommonObj(pThis, &pDir->Core, RTFSISOMAKEROBJTYPE_DIR);
     1477    if (RT_SUCCESS(rc))
     1478    {
     1479        *ppDir = pDir;
     1480        return VINF_SUCCESS;
     1481    }
     1482    RTMemFree(pDir);
     1483    return rc;
     1484
     1485}
     1486
     1487
     1488/**
    9991489 * Adds an unnamed directory to the image.
    10001490 *
     
    10131503    AssertPtrReturn(pidxObj, VERR_INVALID_POINTER);
    10141504
    1015     PRTFSISOMAKERDIR pDir = (PRTFSISOMAKERDIR)RTMemAllocZ(sizeof(*pDir));
    1016     AssertReturn(pDir, VERR_NO_MEMORY);
    1017     int rc = rtFsIsoMakerInitCommonObj(pThis, &pDir->Core, RTFSISOMAKEROBJTYPE_DIR);
    1018     if (RT_SUCCESS(rc))
    1019     {
    1020         *pidxObj = pDir->Core.idxObj;
    1021         return VINF_SUCCESS;
    1022     }
    1023     RTMemFree(pDir);
     1505    PRTFSISOMAKERDIR pDir;
     1506    int rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pDir);
     1507    *pidxObj = RT_SUCCESS(rc) ? pDir->Core.idxObj : UINT32_MAX;
    10241508    return rc;
    10251509}
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