VirtualBox

Changeset 67838 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Jul 6, 2017 4:18:43 PM (7 years ago)
Author:
vboxsync
Message:

IPRT/isomaker: Working on generating rock ridge data (untested). Replaced generic internal error status codes with more specific ones.

File:
1 edited

Legend:

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

    r67801 r67838  
    7777/** UTF-8 name buffer.  */
    7878#define RTFSISOMAKER_MAX_NAME_BUF               768
     79
     80/** Max symbolic link target length.  */
     81#define RTFSISOMAKER_MAX_SYMLINK_TARGET_LEN     260
    7982
    8083/** TRANS.TBL left padding length.
     
    205208    /** Set if pszTransNm is allocated separately.  Normally same as pszSpecNm. */
    206209    bool                    fTransNmAlloced : 1;
     210    /** Set if we need to emit an ER entry (root only). */
     211    bool                    fRockNeedER : 1;
     212    /** Set if we need to emit a RR entry in the directory record. */
     213    bool                    fRockNeedRRInDirRec : 1;
     214    /** Set if we need to emit a RR entry in the spill file. */
     215    bool                    fRockNeedRRInSpill : 1;
    207216
    208217    /** The mode mask.
     
    218227     * This is for Rock Ridge.  */
    219228    RTDEV                   Device;
    220     /** The inode/serial number.
    221      * This is for Rock Ridge.  */
    222     uint64_t                INode;
    223229    /** The number of hardlinks to report in the file stats.
    224230     * This is for Rock Ridge.  */
     
    235241     *  sector zero padding. */
    236242    uint16_t                cbDirRecTotal;
     243
     244    /** Rock ridge flags (ISO9660RRIP_RR_F_XXX). */
     245    uint8_t                 fRockEntries;
     246    /** Number of rock ridge data bytes in the directory record. */
     247    uint8_t                 cbRockInDirRec;
     248    /** Rock ridge spill file data offset, UINT32_MAX if placed in dir record. */
     249    uint32_t                offRockSpill;
     250    /** Size of rock data in spill file. */
     251    uint16_t                cbRockSpill;
    237252
    238253    /** The number of bytes the name requires in the directory record. */
     
    354369    RTFSISOMAKERSRCTYPE_COMMON,
    355370    RTFSISOMAKERSRCTYPE_TRANS_TBL,
     371    RTFSISOMAKERSRCTYPE_RR_SPILL,
    356372    RTFSISOMAKERSRCTYPE_END
    357373} RTFSISOMAKERSRCTYPE;
     
    390406        /** The directory the translation table belongs to. */
    391407        PRTFSISOMAKERNAME   pTransTblDir;
     408        /** The namespace for a rock ridge spill file.. */
     409        PRTFSISOMAKERNAMESPACE pRockSpillNamespace;
    392410    } u;
    393411
     
    423441    /** The common bit. */
    424442    RTFSISOMAKEROBJ         Core;
     443    /** The size of the rock ridge 'SL' records for this link. */
     444    uint16_t                cbSlRockRidge;
    425445    /** The symbolic link target length. */
    426     size_t                  cchTarget;
     446    uint16_t                cchTarget;
    427447    /** The symbolic link target. */
    428448    char                    szTarget[RT_FLEXIBLE_ARRAY];
     
    430450/** Pointer to an ISO maker directory object.  */
    431451typedef RTFSISOMAKERSYMLINK *PRTFSISOMAKERSYMLINK;
     452/** Pointer to a const ISO maker directory object.  */
     453typedef const RTFSISOMAKERSYMLINK *PCRTFSISOMAKERSYMLINK;
    432454
    433455
     
    594616    /** Current directory hint for the joliet namespace. */
    595617    PRTFSISOMAKERNAMEDIR    pDirHintJoliet;
     618    /** Joliet directory child index hint. */
     619    uint32_t                iChildPrimaryIso;
     620    /** Joliet directory child index hint. */
     621    uint32_t                iChildJoliet;
    596622} RTFSISOMAKEROUTPUTFILE;
    597623/** Pointer to the instance data of an ISO maker output file. */
     
    670696static int rtFsIsoMakerObjRemoveWorker(PRTFSISOMAKERINT pThis, PRTFSISOMAKEROBJ pObj);
    671697
     698static ssize_t rtFsIsoMakerOutFile_RockRidgeGenSL(const char *pszTarget, uint8_t *pbBuf, size_t cbBuf);
    672699static DECLCALLBACK(int) rtFsIsoMakerOutFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual);
    673700
     
    686713     */
    687714    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_ISO_9660]].fNamespace == RTFSISOMAKER_NAMESPACE_ISO_9660,
    688                  VERR_INTERNAL_ERROR_5);
     715                 VERR_ISOMK_IPE_TABLE);
    689716    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_JOLIET]].fNamespace   == RTFSISOMAKER_NAMESPACE_JOLIET,
    690                  VERR_INTERNAL_ERROR_5);
     717                 VERR_ISOMK_IPE_TABLE);
    691718    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_UDF]].fNamespace      == RTFSISOMAKER_NAMESPACE_UDF,
    692                  VERR_INTERNAL_ERROR_5);
     719                 VERR_ISOMK_IPE_TABLE);
    693720    AssertReturn(g_aRTFsIsoNamespaces[g_aidxRTFsIsoNamespaceFlagToIdx[RTFSISOMAKER_NAMESPACE_HFS]].fNamespace      == RTFSISOMAKER_NAMESPACE_HFS,
    694                  VERR_INTERNAL_ERROR_5);
     721                 VERR_ISOMK_IPE_TABLE);
    695722
    696723    if (g_szAppIdPrimaryIso[0] == '\0')
     
    870897
    871898            case RTFSISOMAKERSRCTYPE_COMMON:
     899            case RTFSISOMAKERSRCTYPE_RR_SPILL:
    872900                break;
    873901
     
    15441572    while (RTPATH_IS_SLASH(*pszPath))
    15451573        pszPath++;
    1546     AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4);
     1574    AssertReturn(*pszPath, VERR_ISOMK_IPE_EMPTY_PATH);
    15471575
    15481576    PRTFSISOMAKERNAME pCur = pNamespace->pRoot;
     
    16671695                                                      char *pszDst, size_t cbDst, size_t *pcchDst, size_t *pcbInDirRec)
    16681696{
    1669     AssertReturn(cbDst > ISO9660_MAX_NAME_LEN + 2, VERR_INTERNAL_ERROR_3);
     1697    AssertReturn(cbDst > ISO9660_MAX_NAME_LEN + 2, VERR_ISOMK_IPE_BUFFER_SIZE);
    16701698
    16711699    /* Skip leading dots. */
     
    18421870
    18431871            default:
    1844                 AssertFailedReturn(VERR_INTERNAL_ERROR_2);
     1872                AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
    18451873        }
    18461874    }
     
    18571885        *pcchDst     = 0;
    18581886        *pcbInDirRec = pNamespace->fNamespace & (RTFSISOMAKER_NAMESPACE_ISO_9660 | RTFSISOMAKER_NAMESPACE_JOLIET) ? 1 : 0;
    1859         AssertReturn(!pParent, VERR_INTERNAL_ERROR_3);
     1887        AssertReturn(!pParent, VERR_ISOMK_IPE_NAMESPACE_3);
    18601888        return VINF_SUCCESS;
    18611889    }
     
    19701998    if (pParent)
    19711999    {
    1972         AssertReturn(pParent->pDir, VERR_INTERNAL_ERROR_5);
     2000        AssertReturn(pParent->pDir, VERR_ISOMK_IPE_NAMESPACE_1);
    19732001        uint32_t cChildren = pParent->pDir->cChildren;
    19742002        if (cChildren & 31)
     
    19832011    }
    19842012    else
    1985         AssertReturn(pNamespace->pRoot == NULL, VERR_INTERNAL_ERROR_5);
     2013        AssertReturn(pNamespace->pRoot == NULL, VERR_ISOMK_IPE_NAMESPACE_2);
    19862014
    19872015    /*
     
    20232051            pName->fRockRidgeNmAlloced  = false;
    20242052            pName->fTransNmAlloced      = false;
     2053            pName->fRockNeedER          = false;
     2054            pName->fRockNeedRRInDirRec  = false;
     2055            pName->fRockNeedRRInSpill   = false;
    20252056
    20262057            pName->fMode                = pObj->fMode;
     
    20282059            pName->gid                  = pObj->gid;
    20292060            pName->Device               = 0;
    2030             pName->INode                = pObj->idxObj;
    20312061            pName->cHardlinks           = 1;
    20322062            pName->offDirRec            = UINT32_MAX;
     
    20342064            pName->cDirRecs             = 1;
    20352065            pName->cbDirRecTotal        = 0;
     2066            pName->fRockEntries         = 0;
     2067            pName->cbRockInDirRec       = 0;
     2068            pName->offRockSpill         = UINT32_MAX;
     2069            pName->cbRockSpill          = 0;
    20362070
    20372071            memcpy(pName->szName, szName, cchName);
     
    21222156
    21232157    int rc;
    2124     AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INTERNAL_ERROR_4);
     2158    AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_ISOMK_IPE_ROOT_SLASH);
    21252159
    21262160    /*
     
    21292163    while (RTPATH_IS_SLASH(*pszPath))
    21302164        pszPath++;
    2131     AssertReturn(*pszPath, VERR_INTERNAL_ERROR_4); /* We should not be called on a root path. */
     2165    AssertReturn(*pszPath, VERR_ISOMK_IPE_EMPTY_PATH); /* We should not be called on a root path. */
    21322166
    21332167    PRTFSISOMAKERNAME pParent = pNamespace->pRoot;
     
    21452179        AssertRCReturn(rc, rc);
    21462180        pParent = pNamespace->pRoot;
    2147         AssertReturn(pParent, VERR_INTERNAL_ERROR_4);
     2181        AssertReturn(pParent, VERR_ISOMK_IPE_NAMESPACE_4);
    21482182    }
    21492183
     
    21602194        while ((ch = pszPath[cchComponent]) != '\0' && !RTPATH_IS_SLASH(ch))
    21612195            cchComponent++;
    2162         AssertReturn(cchComponent > 0, VERR_INTERNAL_ERROR_4);
     2196        AssertReturn(cchComponent > 0, VERR_ISOMK_IPE_EMPTY_COMPONENT);
    21632197
    21642198        size_t offNext = cchComponent;
     
    22202254                        if (RT_FAILURE(rc))
    22212255                            return rc;
    2222                         AssertReturn(pChild != NULL, VERR_INTERNAL_ERROR_4);
     2256                        AssertReturn(pChild != NULL, VERR_ISOMK_IPE_NAMESPACE_5);
    22232257                    }
    22242258                }
     
    22312265                    if (RT_FAILURE(rc))
    22322266                        return rc;
    2233                     AssertReturn(pChild != NULL, VERR_INTERNAL_ERROR_4);
     2267                    AssertReturn(pChild != NULL, VERR_ISOMK_IPE_NAMESPACE_5);
    22342268                }
    22352269                pParent = pChild;
     
    22582292{
    22592293    AssertReturn(*rtFsIsoMakerObjGetNameForNamespace(pObj, pNamespace) == NULL, VERR_WRONG_ORDER);
    2260     AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_INTERNAL_ERROR_5);
     2294    AssertReturn(RTPATH_IS_SLASH(*pszPath), VERR_ISOMK_IPE_ROOT_SLASH);
    22612295
    22622296    /*
     
    23632397    /* Not found. This can't happen. */
    23642398    AssertFailed();
    2365     return VERR_INTERNAL_ERROR_2;
     2399    return VERR_ISOMK_IPE_NAMESPACE_6;
    23662400}
    23672401
     
    25262560    PRTFSISOMAKEROBJ pObj = rtFsIsoMakerIndexToObj(pThis, idxObj);
    25272561    AssertReturn(pObj, VERR_OUT_OF_RANGE);
     2562    AssertReturn(   pObj->enmType != RTFSISOMAKEROBJTYPE_FILE
     2563                 || ((PRTFSISOMAKERFILE)pObj)->enmSrcType != RTFSISOMAKERSRCTYPE_RR_SPILL, VERR_ACCESS_DENIED);
    25282564    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    25292565
     
    28072843    {
    28082844        PRTFSISOMAKERFILE pFile = (PRTFSISOMAKERFILE)pObj;
    2809         if (pFile->enmSrcType != RTFSISOMAKERSRCTYPE_TRANS_TBL)
     2845        if (   pFile->enmSrcType != RTFSISOMAKERSRCTYPE_TRANS_TBL
     2846            && pFile->enmSrcType != RTFSISOMAKERSRCTYPE_RR_SPILL)
    28102847        {
    28112848            *pcbData = ((PRTFSISOMAKERFILE)pObj)->cbData;
     
    33333370    size_t cchTarget = strlen(pszTarget);
    33343371    AssertPtrReturn(cchTarget > 0, VERR_INVALID_NAME);
    3335     AssertPtrReturn(cchTarget < _1K, VERR_FILENAME_TOO_LONG);
     3372    AssertPtrReturn(cchTarget < RTFSISOMAKER_MAX_SYMLINK_TARGET_LEN, VERR_FILENAME_TOO_LONG);
    33363373    AssertReturn(!pThis->fFinalized, VERR_WRONG_ORDER);
    33373374
     
    33463383
    33473384    /*
     3385     * Calculate the size of the SL entries.
     3386     */
     3387    uint8_t abTmp[_2K + RTFSISOMAKER_MAX_SYMLINK_TARGET_LEN * 3];
     3388    ssize_t cbSlRockRidge = rtFsIsoMakerOutFile_RockRidgeGenSL(pszTarget, abTmp, sizeof(abTmp));
     3389    AssertReturn(cbSlRockRidge > 0, (int)cbSlRockRidge);
     3390
     3391    /*
    33483392     * Do the adding.
    33493393     */
     
    33533397    if (RT_SUCCESS(rc))
    33543398    {
     3399        pSymlink->cchTarget     = (uint16_t)cchTarget;
     3400        pSymlink->cbSlRockRidge = (uint16_t)cbSlRockRidge;
    33553401        memcpy(pSymlink->szTarget, pszTarget, cchTarget);
    33563402        pSymlink->szTarget[cchTarget] = '\0';
    3357         pSymlink->cchTarget = cchTarget;
     3403
    33583404        return VINF_SUCCESS;
    33593405    }
     
    35573603        }
    35583604        else
    3559             rc = VERR_INTERNAL_ERROR_2;
     3605            rc = VERR_ISOMK_IPE_BOOT_CAT_FILE;
    35603606    }
    35613607    return rc;
     
    41024148 * @param   pName           The directory entry to finalize.
    41034149 * @param   offInDir        The offset in the directory of this record.
    4104  * @param   uRootRockRidge  This is the rock ridge level when
    4105  *                          root, otherwise it's zero.
     4150 * @param   uRockRidgeLevel This is the rock ridge level.
     4151 * @param   fIsRoot         Set if this is the root.
    41064152 */
    41074153static int rtFsIsoMakerFinalizeIsoDirectoryEntry(PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs, PRTFSISOMAKERNAME pName,
    4108                                                  uint32_t offInDir, uint8_t uRootRockRidge)
     4154                                                 uint32_t offInDir, uint8_t uRockRidgeLevel, bool fIsRoot)
    41094155{
    41104156    /* Set directory and translation table offsets.  (These are for
     
    41264172
    41274173    /*
    4128      * Calculate additional rock ridge stuff, if it doesn't all fit write it
    4129      * to the spill file.
    4130      */
    4131     if (pFinalizedDirs->pRRSpillFile)
    4132     {
    4133         /** @todo rock ridge    */
    4134         RT_NOREF(uRootRockRidge);
     4174     * Calculate the size of the rock ridge bits we need.
     4175     */
     4176    if (uRockRidgeLevel > 0)
     4177    {
     4178        uint16_t cbRock = 0;
     4179        uint8_t  fFlags = 0;
     4180
     4181        /* Level two starts with a 'RR' entry. */
     4182        if (uRockRidgeLevel >= 2)
     4183            cbRock += sizeof(ISO9660RRIPRR);
     4184
     4185        /* We always do 'PX' and 'TF' w/ 4 timestamps. */
     4186        cbRock = sizeof(ISO9660RRIPPX)
     4187               + RT_OFFSETOF(ISO9660RRIPTF, abPayload) + 4 * sizeof(ISO9660RECTIMESTAMP);
     4188        fFlags |= ISO9660RRIP_RR_F_PX | ISO9660RRIP_RR_F_TF;
     4189
     4190        /* Devices needs 'PN'. */
     4191        if (   RTFS_IS_DEV_BLOCK(pName->pObj->fMode)
     4192            || RTFS_IS_DEV_BLOCK(pName->pObj->fMode))
     4193        {
     4194            cbRock += sizeof(ISO9660RRIPPN);
     4195            fFlags |= ISO9660RRIP_RR_F_PN;
     4196        }
     4197
     4198        /* Usually we need a 'NM' entry too. */
     4199        if (   pName->pszRockRidgeNm != pName->szName
     4200            && pName->cchRockRidgeNm > 0
     4201            && (   pName->cbNameInDirRec != 1
     4202                || (uint8_t)pName->szName[0] > (uint8_t)0x01) )
     4203        {
     4204            cbRock += (pName->cchRockRidgeNm + ISO9660RRIPNM_MAX_NAME_LEN - 1) / ISO9660RRIPNM_MAX_NAME_LEN;
     4205            fFlags |= ISO9660RRIP_RR_F_NM;
     4206        }
     4207
     4208        /* Symbolic links needs a 'SL' entry. */
     4209        if (pName->pObj->enmType == RTFSISOMAKEROBJTYPE_SYMLINK)
     4210        {
     4211            PRTFSISOMAKERSYMLINK pSymlink = (PRTFSISOMAKERSYMLINK)pName->pObj;
     4212            cbRock += pSymlink->cbSlRockRidge;
     4213            fFlags |= ISO9660RRIP_RR_F_SL;
     4214        }
     4215
     4216        /*
     4217         * Decide where stuff goes.  The '.' record of the root dir is special.
     4218         */
     4219        pName->fRockEntries = fFlags;
     4220        if (!fIsRoot)
     4221        {
     4222            if (pName->cbDirRec + cbRock < UINT8_MAX)
     4223            {
     4224                pName->cbRockInDirRec      = cbRock + (cbRock & 1);
     4225                pName->cbRockSpill         = 0;
     4226                pName->fRockNeedRRInDirRec = uRockRidgeLevel >= 2;
     4227                pName->fRockNeedRRInSpill  = false;
     4228            }
     4229            else if (pName->cbDirRec + sizeof(ISO9660SUSPCE) < UINT8_MAX)
     4230            {
     4231                /* Try fit the 'RR' entry in the directory record, but don't bother with anything else. */
     4232                if (uRockRidgeLevel >= 2 && pName->cbDirRec + sizeof(ISO9660SUSPCE) + sizeof(ISO9660RRIPRR) < UINT8_MAX)
     4233                {
     4234                    pName->cbRockInDirRec      = RT_ALIGN_T(sizeof(ISO9660SUSPCE) + sizeof(ISO9660RRIPRR), 2, uint16_t);
     4235                    cbRock -= sizeof(ISO9660RRIPRR);
     4236                    pName->cbRockSpill         = cbRock;
     4237                    pName->fRockNeedRRInDirRec = true;
     4238                    pName->fRockNeedRRInSpill  = false;
     4239                }
     4240                else
     4241                {
     4242                    pName->cbRockInDirRec      = RT_ALIGN_T(sizeof(ISO9660SUSPCE), 2, uint16_t);
     4243                    pName->cbRockSpill         = cbRock;
     4244                    pName->fRockNeedRRInDirRec = false;
     4245                    pName->fRockNeedRRInSpill  = uRockRidgeLevel >= 2;
     4246                }
     4247                if (ISO9660_SECTOR_SIZE - (pFinalizedDirs->pRRSpillFile->cbData & ISO9660_SECTOR_OFFSET_MASK) < cbRock)
     4248                    pFinalizedDirs->pRRSpillFile->cbData = (pFinalizedDirs->pRRSpillFile->cbData | ISO9660_SECTOR_OFFSET_MASK) + 1;
     4249                pName->offRockSpill = pFinalizedDirs->pRRSpillFile->cbData;
     4250                pFinalizedDirs->pRRSpillFile->cbData += RT_ALIGN_T(cbRock, 4, uint16_t);
     4251            }
     4252            else
     4253            {
     4254                LogRel(("RTFsIsoMaker: no space for 'CE' entry: cbDirRec=%#x bytes, name=%s (%#x bytes)\n",
     4255                        pName->cbDirRec, pName->szName, pName->cbNameInDirRec));
     4256                return VERR_ISOMK_RR_NO_SPACE_FOR_CE;
     4257            }
     4258        }
     4259        else
     4260        {
     4261            /* The root starts with a 'SP' record to indicate that SUSP is being used,
     4262               this is always in the directory record.  If we add a 'ER' record (big) too,
     4263               we put all but 'SP' and 'ER' in the spill file too keep things simple. */
     4264            if (uRockRidgeLevel < 2)
     4265            {
     4266                Assert(!(fFlags & (ISO9660RRIP_RR_F_NM | ISO9660RRIP_RR_F_SL | ISO9660RRIP_RR_F_CL | ISO9660RRIP_RR_F_PL | ISO9660RRIP_RR_F_RE)));
     4267                cbRock += sizeof(ISO9660SUSPSP);
     4268                Assert(pName->cbDirRec + cbRock < UINT8_MAX);
     4269                pName->cbRockInDirRec       = cbRock + (cbRock & 1);
     4270                pName->cbRockSpill          = 0;
     4271                pName->fRockNeedER          = false;
     4272                pName->fRockNeedRRInDirRec  = false;
     4273                pName->fRockNeedRRInSpill   = false;
     4274            }
     4275            else
     4276            {
     4277                pName->cbRockInDirRec       = RT_ALIGN_T(sizeof(ISO9660SUSPSP) + sizeof(ISO9660SUSPCE), 2, uint16_t);
     4278                pName->fRockNeedER          = true;
     4279                pName->fRockNeedRRInSpill   = true;
     4280                pName->fRockNeedRRInDirRec  = false;
     4281                cbRock += ISO9660_RRIP_ER_LEN;
     4282                pName->cbRockSpill          = cbRock;
     4283                if ( ISO9660_SECTOR_SIZE - (pFinalizedDirs->pRRSpillFile->cbData & ISO9660_SECTOR_OFFSET_MASK) < cbRock)
     4284                    pFinalizedDirs->pRRSpillFile->cbData = (pFinalizedDirs->pRRSpillFile->cbData | ISO9660_SECTOR_OFFSET_MASK) + 1;
     4285                pName->offRockSpill = pFinalizedDirs->pRRSpillFile->cbData;
     4286                pFinalizedDirs->pRRSpillFile->cbData += RT_ALIGN_T(cbRock, 4, uint16_t);
     4287            }
     4288        }
     4289        pName->cbDirRec += pName->cbRockInDirRec;
     4290        Assert(pName->cbDirRec < UINT8_MAX);
    41354291    }
    41364292
     
    41544310                                                         PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs, uint64_t *poffData)
    41554311{
     4312    int rc;
     4313
    41564314    /* The directory data comes first, so take down it's offset. */
    41574315    pFinalizedDirs->offDirs = *poffData;
     
    41644322    if (pFinalizedDirs->pRRSpillFile)
    41654323    {
     4324        pFinalizedDirs->pRRSpillFile->Core.cNotOrphan = 0;
    41664325        rtFsIsoMakerObjRemoveWorker(pThis, &pFinalizedDirs->pRRSpillFile->Core);
    41674326        pFinalizedDirs->pRRSpillFile = NULL;
     
    41694328    if (pNamespace->uRockRidgeLevel > 0)
    41704329    {
    4171         /** @todo create rock ridge spill file to indicate rock ridge */
    4172     }
    4173 
    4174     int      rc;
     4330        rc = rtFsIsoMakerAddUnnamedFileWorker(pThis, NULL, 0, &pFinalizedDirs->pRRSpillFile);
     4331        AssertRCReturn(rc, rc);
     4332        pFinalizedDirs->pRRSpillFile->enmSrcType            = RTFSISOMAKERSRCTYPE_RR_SPILL;
     4333        pFinalizedDirs->pRRSpillFile->u.pRockSpillNamespace = pNamespace;
     4334        pFinalizedDirs->pRRSpillFile->Core.cNotOrphan       = 1;
     4335    }
     4336
    41754337    uint16_t idPathTable = 1;
    41764338    uint32_t cbPathTable = 0;
     
    41804342         * Precalc the directory record size for the root directory.
    41814343         */
    4182         rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/, pNamespace->uRockRidgeLevel);
     4344        rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pNamespace->pRoot, 0 /*offInDir*/,
     4345                                                   pNamespace->uRockRidgeLevel, true /*fIsRoot*/);
    41834346        AssertRCReturn(rc, rc);
    41844347
     
    42034366
    42044367            /* Finalize the directory entries. */
     4368            uint32_t            cSubDirs    = 0;
    42054369            uint32_t            cbTransTbl  = 0;
    42064370            uint32_t            cLeft       = pCurDir->cChildren;
     
    42094373            {
    42104374                PRTFSISOMAKERNAME pChild = *ppChild++;
    4211                 rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir, 0 /*uRootRockRidge*/);
     4375                rc = rtFsIsoMakerFinalizeIsoDirectoryEntry(pFinalizedDirs, pChild, offInDir,
     4376                                                           pNamespace->uRockRidgeLevel, false /*fIsRoot*/);
    42124377                AssertRCReturn(rc, rc);
    42134378
     
    42344399                               +  pChild->cchTransNm
    42354400                               +  1 /* newline */;
     4401
     4402                if (RTFS_IS_DIRECTORY(pChild->fMode))
     4403                    cSubDirs++;
    42364404            }
    42374405
     
    42524420            pCurDir->idPathTable  = idPathTable++;
    42534421            cbPathTable += RTFSISOMAKER_CALC_PATHREC_SIZE(pCurName->cbNameInDirRec);
     4422
     4423            /* Set the hardlink count. */
     4424            pCurName->cHardlinks = cSubDirs + 2;
    42544425
    42554426            Log4(("rtFsIsoMakerFinalizeDirectoriesInIsoNamespace: idxObj=#%#x cbDir=%#08x cChildren=%#05x %s\n",
     
    43804551                        break;
    43814552                    default:
    4382                         AssertMsgFailedReturn(("enmSrcType=%d\n", pCurFile->enmSrcType), VERR_INTERNAL_ERROR_3);
     4553                        AssertMsgFailedReturn(("enmSrcType=%d\n", pCurFile->enmSrcType), VERR_IPE_NOT_REACHED_DEFAULT_CASE);
    43834554                }
    43844555
     
    46014772        /** @todo UDF descriptors. */
    46024773    }
    4603     AssertReturn(offVolDescs == pThis->cVolumeDescriptors * RTFSISOMAKER_SECTOR_SIZE, VERR_INTERNAL_ERROR_2);
     4774    AssertReturn(offVolDescs == pThis->cVolumeDescriptors * RTFSISOMAKER_SECTOR_SIZE, VERR_ISOMK_IPE_DESC_COUNT);
    46044775
    46054776    /*
     
    47374908static int rtFsIsoMakerFinalizeVolumeDescriptors(PRTFSISOMAKERINT pThis)
    47384909{
    4739     AssertReturn(pThis->pbVolDescs && pThis->pPrimaryVolDesc && pThis->pTerminatorVolDesc, VERR_INTERNAL_ERROR_3);
     4910    AssertReturn(pThis->pbVolDescs && pThis->pPrimaryVolDesc && pThis->pTerminatorVolDesc, VERR_ISOMK_IPE_FINALIZE_1);
    47404911
    47414912    /*
     
    49505121
    49515122/**
     5123 * Generates the 'SL' records for a symbolic link.
     5124 *
     5125 * This is used both when generating directories records, spill file data and
     5126 * when creating the symbolic link.
     5127 *
     5128 * @returns Number of bytes produced.  Negative IPRT status if buffer overflow.
     5129 * @param   pszTarget   The symbolic link target to encode.
     5130 * @param   pbBuf       The output buffer.
     5131 * @param   cbBuf       The size of the output buffer.
     5132 */
     5133static ssize_t rtFsIsoMakerOutFile_RockRidgeGenSL(const char *pszTarget, uint8_t *pbBuf, size_t cbBuf)
     5134{
     5135    Assert(*pszTarget != '\0');
     5136
     5137    PISO9660RRIPSL pEntry = (PISO9660RRIPSL)pbBuf;
     5138    pEntry->Hdr.bSig1    = ISO9660RRIPSL_SIG1;
     5139    pEntry->Hdr.bSig2    = ISO9660RRIPSL_SIG2;
     5140    pEntry->Hdr.cbEntry  = 0; /* set later. */
     5141    pEntry->Hdr.bVersion = ISO9660RRIPSL_VER;
     5142    pEntry->fFlags       = 0;
     5143    size_t  offEntry = 0;
     5144    size_t  off      = pEntry->Hdr.cbEntry;
     5145
     5146    /* Does it start with a root slash? */
     5147    if (RTPATH_IS_SLASH(*pszTarget))
     5148    {
     5149        pbBuf[off++] = ISO9660RRIP_SL_C_ROOT;
     5150        pbBuf[off++] = 0;
     5151        pszTarget++;
     5152    }
     5153
     5154    for (;;)
     5155    {
     5156        /* Find the end of the component. */
     5157        size_t cchComponent = 0;
     5158        char   ch;
     5159        while ((ch = pszTarget[cchComponent]) != '\0' && !RTPATH_IS_SLASH(ch))
     5160            cchComponent++;
     5161
     5162        /* Check for dots and figure out how much space we need. */
     5163        uint8_t fFlags;
     5164        size_t  cbNeeded;
     5165        if (cchComponent == 1 && *pszTarget == '.')
     5166        {
     5167            fFlags   = ISO9660RRIP_SL_C_CURRENT;
     5168            cbNeeded = 2;
     5169        }
     5170        else if (cchComponent == 2 && pszTarget[0] == '.' && pszTarget[1] == '.')
     5171        {
     5172            fFlags   = ISO9660RRIP_SL_C_PARENT;
     5173            cbNeeded = 0;
     5174        }
     5175        else
     5176        {
     5177            fFlags   = 0;
     5178            cbNeeded = 2 + cchComponent;
     5179        }
     5180
     5181        /* Split the SL record if we're out of space. */
     5182        if (   off - offEntry + cbNeeded < UINT8_MAX
     5183            && off + cbNeeded <= cbBuf)
     5184        { /* likely */ }
     5185        else if (cbNeeded + RT_OFFSETOF(ISO9660RRIPSL, abComponents) < UINT8_MAX)
     5186        {
     5187            AssertReturn(off + cbNeeded + RT_OFFSETOF(ISO9660RRIPSL, abComponents) <= cbBuf, VERR_BUFFER_OVERFLOW);
     5188            Assert(off - offEntry < UINT8_MAX);
     5189            pEntry->Hdr.cbEntry = (uint8_t)(off - offEntry);
     5190            pEntry->fFlags |= ISO9660RRIP_SL_F_CONTINUE;
     5191
     5192            offEntry = off;
     5193            pEntry = (PISO9660RRIPSL)&pbBuf[off];
     5194            pEntry->Hdr.bSig1    = ISO9660RRIPSL_SIG1;
     5195            pEntry->Hdr.bSig2    = ISO9660RRIPSL_SIG2;
     5196            pEntry->Hdr.cbEntry  = 0; /* set later. */
     5197            pEntry->Hdr.bVersion = ISO9660RRIPSL_VER;
     5198            pEntry->fFlags       = 0;
     5199        }
     5200        else
     5201        {
     5202            /* Special case: component doesn't fit in a single SL entry. */
     5203            do
     5204            {
     5205                if (off - offEntry + 3 < UINT8_MAX)
     5206                {
     5207                    size_t cchLeft   = UINT8_MAX - 1 - (off - offEntry) - 2;
     5208                    size_t cchToCopy = RT_MIN(cchLeft, cchComponent);
     5209                    AssertReturn(off + 2 + cchToCopy <= cbBuf, VERR_BUFFER_OVERFLOW);
     5210                    pbBuf[off++] = cchToCopy < cchComponent ? ISO9660RRIP_SL_C_CONTINUE : 0;
     5211                    pbBuf[off++] = (uint8_t)cchToCopy;
     5212                    memcpy(&pbBuf[off], pszTarget, cchToCopy);
     5213                    off          += pbBuf[off++];
     5214                    pszTarget    += cchToCopy;
     5215                    cchComponent -= cchToCopy;
     5216                    if (!cchComponent)
     5217                        break;
     5218                }
     5219
     5220                Assert(off - offEntry < UINT8_MAX);
     5221                pEntry->Hdr.cbEntry = (uint8_t)(off - offEntry);
     5222                pEntry->fFlags |= ISO9660RRIP_SL_F_CONTINUE;
     5223
     5224                AssertReturn(off + 2 + cchComponent + RT_OFFSETOF(ISO9660RRIPSL, abComponents) <= cbBuf, VERR_BUFFER_OVERFLOW);
     5225                offEntry = off;
     5226                pEntry = (PISO9660RRIPSL)&pbBuf[off];
     5227                pEntry->Hdr.bSig1    = ISO9660RRIPSL_SIG1;
     5228                pEntry->Hdr.bSig2    = ISO9660RRIPSL_SIG2;
     5229                pEntry->Hdr.cbEntry  = 0; /* set later. */
     5230                pEntry->Hdr.bVersion = ISO9660RRIPSL_VER;
     5231                pEntry->fFlags       = 0;
     5232
     5233
     5234            } while (cchComponent > 0);
     5235            if (ch == '\0')
     5236                break;
     5237            continue;
     5238        }
     5239
     5240        /* Produce the record. */
     5241        pbBuf[off++] = fFlags;
     5242        pbBuf[off++] = (uint8_t)(cbNeeded - 2);
     5243        if (cchComponent > 0)
     5244        {
     5245            memcpy(&pbBuf[off], pszTarget, cbNeeded - 2);
     5246            off += cbNeeded - 2;
     5247        }
     5248
     5249        if (ch == '\0')
     5250            break;
     5251        pszTarget += cchComponent;
     5252    }
     5253
     5254    Assert(off - offEntry < UINT8_MAX);
     5255    pEntry->Hdr.cbEntry = (uint8_t)(off - offEntry);
     5256    return off;
     5257}
     5258
     5259
     5260/**
     5261 * Generates rock ridge data.
     5262 *
     5263 * This is used both for the directory record and for the spill file ('CE').
     5264 *
     5265 * @param   pName           The name to generate rock ridge info for.
     5266 * @param   pbSys           The output buffer.
     5267 * @param   cbSys           The size of the output buffer.
     5268 * @param   fInSpill        Indicates whether we're in a spill file (true) or
     5269 *                          directory record (false).
     5270 */
     5271static void rtFsIosMakerOutFile_GenerateRockRidge(PRTFSISOMAKERNAME pName, uint8_t *pbSys, size_t cbSys, bool fInSpill)
     5272{
     5273    /*
     5274     * Deal with records specific to the root directory '.' entry.
     5275     */
     5276    if (pName->pParent != NULL)
     5277    { /* likely */ }
     5278    else
     5279    {
     5280        if (!fInSpill)
     5281        {
     5282            PISO9660SUSPSP  pSP = (PISO9660SUSPSP)pbSys;
     5283            Assert(cbSys >= sizeof(*pSP));
     5284            pSP->Hdr.bSig1      = ISO9660SUSPSP_SIG1;
     5285            pSP->Hdr.bSig2      = ISO9660SUSPSP_SIG2;
     5286            pSP->Hdr.cbEntry    = ISO9660SUSPSP_LEN;
     5287            pSP->Hdr.bVersion   = ISO9660SUSPSP_VER;
     5288            pSP->bCheck1        = ISO9660SUSPSP_CHECK1;
     5289            pSP->bCheck2        = ISO9660SUSPSP_CHECK2;
     5290            pSP->cbSkip         = 0;
     5291            pbSys += sizeof(*pSP);
     5292            cbSys -= sizeof(*pSP);
     5293        }
     5294        if (pName->fRockNeedER)
     5295        {
     5296            PISO9660SUSPER  pER = (PISO9660SUSPER)pbSys;
     5297            Assert(cbSys >= ISO9660_RRIP_ER_LEN);
     5298            AssertCompile(ISO9660_RRIP_ER_LEN < UINT8_MAX);
     5299            pER->Hdr.bSig1      = ISO9660SUSPER_SIG1;
     5300            pER->Hdr.bSig2      = ISO9660SUSPER_SIG2;
     5301            pER->Hdr.cbEntry    = ISO9660_RRIP_ER_LEN;
     5302            pER->Hdr.bVersion   = ISO9660SUSPER_VER;
     5303            pER->cchIdentifier  = sizeof(ISO9660_RRIP_ID)   - 1;
     5304            pER->cchDescription = sizeof(ISO9660_RRIP_DESC) - 1;
     5305            pER->cchSource      = sizeof(ISO9660_RRIP_SRC)  - 1;
     5306            memcpy(&pER->achPayload[0], RT_STR_TUPLE(ISO9660_RRIP_ID));
     5307            memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID)], RT_STR_TUPLE(ISO9660_RRIP_DESC));
     5308            memcpy(&pER->achPayload[sizeof(ISO9660_RRIP_ID) + sizeof(ISO9660_RRIP_DESC)], RT_STR_TUPLE(ISO9660_RRIP_SRC));
     5309            pbSys += ISO9660_RRIP_ER_LEN;
     5310            cbSys -= ISO9660_RRIP_ER_LEN;
     5311        }
     5312    }
     5313
     5314    /*
     5315     * Deal with common stuff.
     5316     */
     5317    if (!fInSpill ? pName->fRockNeedRRInDirRec : pName->fRockNeedRRInSpill)
     5318    {
     5319        PISO9660RRIPRR  pRR = (PISO9660RRIPRR)pbSys;
     5320        Assert(cbSys >= sizeof(*pRR));
     5321        pRR->Hdr.bSig1      = ISO9660RRIPRR_SIG1;
     5322        pRR->Hdr.bSig2      = ISO9660RRIPRR_SIG2;
     5323        pRR->Hdr.cbEntry    = ISO9660RRIPRR_LEN;
     5324        pRR->Hdr.bVersion   = ISO9660RRIPRR_VER;
     5325        pRR->fFlags         = pName->fRockEntries;
     5326        pbSys += sizeof(*pRR);
     5327        cbSys -= sizeof(*pRR);
     5328    }
     5329
     5330    if (pName->fRockEntries & ISO9660RRIP_RR_F_PX)
     5331    {
     5332        PISO9660RRIPPX pPX = (PISO9660RRIPPX)pbSys;
     5333        Assert(cbSys >= sizeof(*pPX));
     5334        pPX->Hdr.bSig1      = ISO9660RRIPPX_SIG1;
     5335        pPX->Hdr.bSig2      = ISO9660RRIPPX_SIG2;
     5336        pPX->Hdr.cbEntry    = ISO9660RRIPPX_LEN;
     5337        pPX->Hdr.bVersion   = ISO9660RRIPPX_VER;
     5338        pPX->fMode.be       = RT_H2BE_U32((uint32_t)pName->fMode);
     5339        pPX->fMode.le       = RT_H2LE_U32((uint32_t)pName->fMode);
     5340        pPX->cHardlinks.be  = RT_H2BE_U32((uint32_t)pName->cHardlinks);
     5341        pPX->cHardlinks.le  = RT_H2LE_U32((uint32_t)pName->cHardlinks);
     5342        pPX->uid.be         = RT_H2BE_U32((uint32_t)pName->uid);
     5343        pPX->uid.le         = RT_H2LE_U32((uint32_t)pName->uid);
     5344        pPX->gid.be         = RT_H2BE_U32((uint32_t)pName->gid);
     5345        pPX->gid.le         = RT_H2LE_U32((uint32_t)pName->gid);
     5346        pPX->INode.be       = RT_H2BE_U32((uint32_t)pName->pObj->idxObj);
     5347        pPX->INode.le       = RT_H2LE_U32((uint32_t)pName->pObj->idxObj);
     5348        pbSys += sizeof(*pPX);
     5349        cbSys -= sizeof(*pPX);
     5350    }
     5351
     5352    if (pName->fRockEntries & ISO9660RRIP_RR_F_TF)
     5353    {
     5354        PISO9660RRIPTF pTF = (PISO9660RRIPTF)pbSys;
     5355        pTF->Hdr.bSig1      = ISO9660RRIPTF_SIG1;
     5356        pTF->Hdr.bSig2      = ISO9660RRIPTF_SIG2;
     5357        pTF->Hdr.cbEntry    = Iso9660RripTfCalcLength(ISO9660RRIPTF_F_BIRTH | ISO9660RRIPTF_F_MODIFY | ISO9660RRIPTF_F_ACCESS | ISO9660RRIPTF_F_CHANGE);
     5358        Assert(cbSys >= pTF->Hdr.cbEntry);
     5359        pTF->Hdr.bVersion   = ISO9660RRIPTF_VER;
     5360        pTF->fFlags         = ISO9660RRIPTF_F_BIRTH | ISO9660RRIPTF_F_MODIFY | ISO9660RRIPTF_F_ACCESS | ISO9660RRIPTF_F_CHANGE;
     5361        PISO9660RECTIMESTAMP paTimestamps = (PISO9660RECTIMESTAMP)&pTF->abPayload[0];
     5362        rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->BirthTime,        &paTimestamps[0]);
     5363        rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->ModificationTime, &paTimestamps[1]);
     5364        rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->AccessedTime,     &paTimestamps[2]);
     5365        rtFsIsoMakerTimespecToIso9660RecTimestamp(&pName->pObj->ChangeTime,       &paTimestamps[3]);
     5366        cbSys += pTF->Hdr.cbEntry;
     5367        pbSys += pTF->Hdr.cbEntry;
     5368    }
     5369
     5370    if (pName->fRockEntries & ISO9660RRIP_RR_F_PN)
     5371    {
     5372        PISO9660RRIPPN pPN = (PISO9660RRIPPN)pbSys;
     5373        Assert(cbSys >= sizeof(*pPN));
     5374        pPN->Hdr.bSig1      = ISO9660RRIPPN_SIG1;
     5375        pPN->Hdr.bSig2      = ISO9660RRIPPN_SIG2;
     5376        pPN->Hdr.cbEntry    = ISO9660RRIPPN_LEN;
     5377        pPN->Hdr.bVersion   = ISO9660RRIPPN_VER;
     5378        pPN->Major.be       = RT_H2BE_U32((uint32_t)RTDEV_MAJOR(pName->Device));
     5379        pPN->Major.le       = RT_H2LE_U32((uint32_t)RTDEV_MAJOR(pName->Device));
     5380        pPN->Minor.be       = RT_H2BE_U32((uint32_t)RTDEV_MINOR(pName->Device));
     5381        pPN->Minor.le       = RT_H2LE_U32((uint32_t)RTDEV_MINOR(pName->Device));
     5382    }
     5383
     5384    if (pName->fRockEntries & ISO9660RRIP_RR_F_NM)
     5385    {
     5386        size_t      cchSrc = pName->cchRockRidgeNm;
     5387        const char *pszSrc = pName->pszRockRidgeNm;
     5388        for (;;)
     5389        {
     5390            size_t         cchThis = RT_MIN(cchSrc, ISO9660RRIPNM_MAX_NAME_LEN);
     5391            PISO9660RRIPNM pNM     = (PISO9660RRIPNM)pbSys;
     5392            Assert(cbSys >= RT_OFFSETOF(ISO9660RRIPNM, achName[cchThis]));
     5393            pNM->Hdr.bSig1      = ISO9660RRIPNM_SIG1;
     5394            pNM->Hdr.bSig2      = ISO9660RRIPNM_SIG2;
     5395            pNM->Hdr.cbEntry    = (uint8_t)(RT_OFFSETOF(ISO9660RRIPNM, achName) + cchThis);
     5396            pNM->Hdr.bVersion   = ISO9660RRIPNM_VER;
     5397            pNM->fFlags         = cchThis == cchSrc ? 0 : ISO9660RRIP_NM_F_CONTINUE;
     5398            memcpy(&pNM->achName[0], pszSrc, cchThis);
     5399            pbSys  += RT_OFFSETOF(ISO9660RRIPNM, achName) + cchThis;
     5400            cbSys  -= RT_OFFSETOF(ISO9660RRIPNM, achName) + cchThis;
     5401            cchSrc -= cchThis;
     5402            if (!cchSrc)
     5403                break;
     5404        }
     5405    }
     5406
     5407    if (pName->fRockEntries & ISO9660RRIP_RR_F_SL)
     5408    {
     5409        AssertReturnVoid(pName->pObj->enmType == RTFSISOMAKEROBJTYPE_SYMLINK);
     5410        PCRTFSISOMAKERSYMLINK pSymlink = (PCRTFSISOMAKERSYMLINK)pName->pObj;
     5411
     5412        ssize_t cbSlRockRidge = rtFsIsoMakerOutFile_RockRidgeGenSL(pSymlink->szTarget, pbSys, cbSys);
     5413        AssertReturnVoid(cbSlRockRidge > 0);
     5414        Assert(cbSys >= (size_t)cbSlRockRidge);
     5415        cbSys -= (size_t)cbSlRockRidge;
     5416        pbSys -= (size_t)cbSlRockRidge;
     5417    }
     5418
     5419    /* finally, zero padding. */
     5420    if (cbSys & 1)
     5421    {
     5422        *pbSys++ = '\0';
     5423        cbSys--;
     5424    }
     5425
     5426    Assert(cbSys == 0);
     5427}
     5428
     5429
     5430
     5431
     5432/**
     5433 * Reads one or more sectors from a rock ridge spill file.
     5434 *
     5435 * @returns IPRT status code.
     5436 * @param   pThis       The ISO maker output file instance.  We use the
     5437 *                      directory pointer hints and child index hints
     5438 * @param   pIsoMaker   The ISO maker.
     5439 * @param   pFile       The rock ridge spill file.
     5440 * @param   offInFile   The offset into the spill file.  This is sector aligned.
     5441 * @param   pbBuf       The output buffer.
     5442 * @param   cbToRead    The number of bytes to tread.  This is sector aligned.
     5443 */
     5444static int rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERINT pIsoMaker,
     5445                                                         PRTFSISOMAKERFILE pFile, uint32_t offInFile, uint8_t *pbBuf,
     5446                                                         size_t cbToRead)
     5447{
     5448    /*
     5449     * We're only working multiple of ISO 9660 sectors.
     5450     *
     5451     * The spill of one directory record will always fit entirely within a
     5452     * sector, we make sure about that during finalization.  There may be
     5453     * zero padding between spill data sequences, especially on the sector
     5454     * boundrary.
     5455     */
     5456    Assert((offInFile & ISO9660_SECTOR_OFFSET_MASK) == 0);
     5457    Assert((cbToRead  & ISO9660_SECTOR_OFFSET_MASK) == 0);
     5458    Assert(cbToRead  >= ISO9660_SECTOR_SIZE);
     5459
     5460    /*
     5461     * We generate a sector at a time.
     5462     *
     5463     * So, we start by locating the first directory/child in the block offInFile
     5464     * is pointing to.
     5465     */
     5466    PRTFSISOMAKERFINALIZEDDIRS  pFinalizedDirs;
     5467    PRTFSISOMAKERNAMEDIR       *ppDirHint;
     5468    uint32_t                   *pidxChildHint;
     5469    if (pFile->u.pRockSpillNamespace->fNamespace & RTFSISOMAKER_NAMESPACE_ISO_9660)
     5470    {
     5471        pFinalizedDirs = &pIsoMaker->PrimaryIsoDirs;
     5472        ppDirHint      = &pThis->pDirHintPrimaryIso;
     5473        pidxChildHint  = &pThis->iChildPrimaryIso;
     5474    }
     5475    else
     5476    {
     5477        pFinalizedDirs = &pIsoMaker->JolietDirs;
     5478        ppDirHint      = &pThis->pDirHintJoliet;
     5479        pidxChildHint  = &pThis->iChildJoliet;
     5480    }
     5481
     5482    /* Special case: '.' record in root dir */
     5483    uint32_t             idxChild  = *pidxChildHint;
     5484    PRTFSISOMAKERNAMEDIR pDir      = *ppDirHint;
     5485    if (   offInFile == 0
     5486        && (pDir = RTListGetFirst(&pFinalizedDirs->FinalizedDirs, RTFSISOMAKERNAMEDIR, FinalizedEntry)) != NULL
     5487        && pDir->pName->cbRockSpill > 0)
     5488    {
     5489        AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ);
     5490        AssertReturn(pDir->pName->offRockSpill == 0, VERR_ISOMK_IPE_RR_READ);
     5491        idxChild = 0;
     5492    }
     5493    else
     5494    {
     5495        /* Establish where to start searching from. */
     5496        if (  !pDir
     5497            || idxChild >= pDir->cChildren
     5498            || pDir->papChildren[idxChild]->cbRockSpill == 0)
     5499        {
     5500            idxChild = 0;
     5501            pDir = RTListGetFirst(&pFinalizedDirs->FinalizedDirs, RTFSISOMAKERNAMEDIR, FinalizedEntry);
     5502            AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ);
     5503        }
     5504
     5505        if (pDir->papChildren[idxChild]->offRockSpill == offInFile)
     5506        { /* hit, no need to search */ }
     5507        else if (pDir->papChildren[idxChild]->offRockSpill < offInFile)
     5508        {
     5509            /* search forwards */
     5510            for (;;)
     5511            {
     5512                idxChild++;
     5513                while (   idxChild < pDir->cChildren
     5514                       && (   pDir->papChildren[idxChild]->offRockSpill < offInFile
     5515                           || pDir->papChildren[idxChild]->cbRockSpill  == 0) )
     5516                    idxChild++;
     5517                if (idxChild < pDir->cChildren)
     5518                    break;
     5519                pDir = RTListGetNext(&pFinalizedDirs->FinalizedDirs, pDir, RTFSISOMAKERNAMEDIR, FinalizedEntry);
     5520                AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ);
     5521            }
     5522            Assert(pDir->papChildren[idxChild]->offRockSpill == offInFile);
     5523        }
     5524        else
     5525        {
     5526            /* search backwards (no root dir concerns here) */
     5527            for (;;)
     5528            {
     5529                while (   idxChild > 0
     5530                       && (   pDir->papChildren[idxChild - 1]->offRockSpill >= offInFile
     5531                           || pDir->papChildren[idxChild - 1]->cbRockSpill  == 0) )
     5532                    idxChild--;
     5533                if (pDir->papChildren[idxChild]->offRockSpill == offInFile)
     5534                    break;
     5535                pDir = RTListGetPrev(&pFinalizedDirs->FinalizedDirs, pDir, RTFSISOMAKERNAMEDIR, FinalizedEntry);
     5536                AssertReturn(pDir, VERR_ISOMK_IPE_RR_READ);
     5537            }
     5538            Assert(pDir->papChildren[idxChild]->offRockSpill == offInFile);
     5539        }
     5540    }
     5541
     5542    /*
     5543     * Produce data.
     5544     */
     5545    while (cbToRead > 0)
     5546    {
     5547        PRTFSISOMAKERNAME pChild;
     5548        if (   offInFile > 0
     5549            || pDir->pName->cbRockSpill == 0
     5550            || pDir->pName->pParent     != NULL)
     5551        {
     5552            pChild = pDir->papChildren[idxChild];
     5553            AssertReturn(pChild->offRockSpill == offInFile, VERR_ISOMK_IPE_RR_READ);
     5554            AssertReturn(pChild->cbRockSpill > 0, VERR_ISOMK_IPE_RR_READ);
     5555            idxChild++;
     5556        }
     5557        else
     5558        {   /* root dir special case. */
     5559            pChild = pDir->pName;
     5560            Assert(idxChild == 0);
     5561            Assert(pChild->pParent == NULL);
     5562        }
     5563
     5564        AssertReturn(cbToRead >= pChild->cbRockSpill, VERR_ISOMK_IPE_RR_READ);
     5565        rtFsIosMakerOutFile_GenerateRockRidge(pDir->pName, pbBuf, cbToRead, true /*fInSpill*/);
     5566        cbToRead  -= pChild->cbRockSpill;
     5567        pbBuf     += pChild->cbRockSpill;
     5568        offInFile += pChild->cbRockSpill;
     5569
     5570        /* Advance to the next name, if any. */
     5571        uint32_t offNext = UINT32_MAX;
     5572        do
     5573        {
     5574            while (idxChild < pDir->cChildren)
     5575            {
     5576                pChild = pDir->papChildren[idxChild];
     5577                if (pChild->cbRockSpill == 0)
     5578                    Assert(pChild->offRockSpill == UINT32_MAX);
     5579                else
     5580                {
     5581                    offNext = pChild->offRockSpill;
     5582                    AssertReturn(offNext >= offInFile, VERR_ISOMK_IPE_RR_READ);
     5583                    AssertReturn(offNext < pFile->cbData, VERR_ISOMK_IPE_RR_READ);
     5584                    break;
     5585                }
     5586                idxChild++;
     5587            }
     5588            pDir     = RTListGetNext(&pFinalizedDirs->FinalizedDirs, pDir, RTFSISOMAKERNAMEDIR, FinalizedEntry);
     5589            idxChild = 0;
     5590        } while (pDir != NULL);
     5591
     5592        if (offNext != UINT32_MAX)
     5593        {
     5594            uint32_t cbToZero = offNext - offInFile;
     5595            if (cbToRead > cbToZero)
     5596                RT_BZERO(pbBuf, cbToZero);
     5597            else
     5598            {
     5599                RT_BZERO(pbBuf, cbToRead);
     5600                *ppDirHint     = pDir;
     5601                *pidxChildHint = idxChild;
     5602                break;
     5603            }
     5604        }
     5605        else
     5606        {
     5607            RT_BZERO(pbBuf, cbToRead);
     5608            *ppDirHint     = NULL;
     5609            *pidxChildHint = UINT32_MAX;
     5610            break;
     5611        }
     5612    }
     5613
     5614    return VINF_SUCCESS;
     5615}
     5616
     5617
     5618/**
     5619 * Deals with reads that aren't an exact multiple of sectors.
     5620 *
     5621 * @returns IPRT status code.
     5622 * @param   pThis       The ISO maker output file instance.  We use the
     5623 *                      directory pointer hints and child index hints
     5624 * @param   pIsoMaker   The ISO maker.
     5625 * @param   pFile       The rock ridge spill file.
     5626 * @param   offInFile   The offset into the spill file.
     5627 * @param   pbBuf       The output buffer.
     5628 * @param   cbToRead    The number of bytes to tread.
     5629 */
     5630static int rtFsIsoMakerOutFile_RockRidgeSpillReadUnaligned(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERINT pIsoMaker,
     5631                                                           PRTFSISOMAKERFILE pFile, uint32_t offInFile, uint8_t *pbBuf,
     5632                                                           uint32_t cbToRead)
     5633{
     5634    for (;;)
     5635    {
     5636        /*
     5637         * Deal with unnaligned file offsets and sub-sector sized reads.
     5638         */
     5639        if (   (offInFile & ISO9660_SECTOR_OFFSET_MASK)
     5640            || cbToRead < ISO9660_SECTOR_SIZE)
     5641        {
     5642            uint8_t abSectorBuf[ISO9660_SECTOR_SIZE];
     5643            int rc = rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(pThis, pIsoMaker, pFile,
     5644                                                                   offInFile & ~(uint32_t)ISO9660_SECTOR_OFFSET_MASK,
     5645                                                                   abSectorBuf, sizeof(abSectorBuf));
     5646            if (RT_FAILURE(rc))
     5647                return rc;
     5648            uint32_t offSrcBuf = (size_t)offInFile & (size_t)ISO9660_SECTOR_OFFSET_MASK;
     5649            uint32_t cbToCopy  = RT_MIN(ISO9660_SECTOR_SIZE - offSrcBuf, cbToRead);
     5650            memcpy(pbBuf, &abSectorBuf[offSrcBuf], cbToCopy);
     5651            if (cbToCopy >= cbToRead)
     5652                return VINF_SUCCESS;
     5653            cbToRead  -= cbToCopy;
     5654            offInFile += cbToCopy;
     5655            pbBuf     += cbToCopy;
     5656        }
     5657
     5658        /*
     5659         * The offset is aligned now, so try read some sectors directly into the buffer.
     5660         */
     5661        AssertContinue((offInFile & ISO9660_SECTOR_OFFSET_MASK) == 0);
     5662        if (cbToRead >= ISO9660_SECTOR_SIZE)
     5663        {
     5664            uint32_t cbFullSectors = cbToRead & ~(uint32_t)ISO9660_SECTOR_OFFSET_MASK;
     5665            int rc = rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(pThis, pIsoMaker, pFile, offInFile, pbBuf, cbFullSectors);
     5666            if (RT_FAILURE(rc))
     5667                return rc;
     5668            if (cbFullSectors >= cbToRead)
     5669                return VINF_SUCCESS;
     5670            cbToRead  -= cbFullSectors;
     5671            offInFile += cbFullSectors;
     5672            pbBuf     += cbFullSectors;
     5673        }
     5674    }
     5675}
     5676
     5677
     5678
     5679/**
    49525680 * Produces the content of a TRANS.TBL file as a memory file.
    49535681 *
     
    50035731    AssertMsgFailed(("rc=%Rrc, cbResult=%#RX64 cbData=%#RX64\n", rc, cbResult, pFile->cbData));
    50045732    RTVfsFileRelease(hVfsFile);
    5005     return VERR_INTERNAL_ERROR_4;
     5733    return VERR_ISOMK_IPE_PRODUCE_TRANS_TBL;
    50065734}
    50075735
     
    50345762    {
    50355763        pFile = RTListGetFirst(&pIsoMaker->FinalizedFiles, RTFSISOMAKERFILE, FinalizedEntry);
    5036         AssertReturn(pFile, VERR_INTERNAL_ERROR_2);
     5764        AssertReturn(pFile, VERR_ISOMK_IPE_READ_FILE_DATA_1);
    50375765    }
    50385766    if ((offInFile = offUnsigned - pFile->offData) < RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE))
     
    50445772        {
    50455773            pFile = RTListGetNext(&pIsoMaker->FinalizedFiles, pFile, RTFSISOMAKERFILE, FinalizedEntry);
    5046             AssertReturn(pFile, VERR_INTERNAL_ERROR_3);
     5774            AssertReturn(pFile, VERR_ISOMK_IPE_READ_FILE_DATA_2);
    50475775        } while ((offInFile = offUnsigned - pFile->offData) >= RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE));
    50485776    }
     
    50535781        {
    50545782            pFile = RTListGetPrev(&pIsoMaker->FinalizedFiles, pFile, RTFSISOMAKERFILE, FinalizedEntry);
    5055             AssertReturn(pFile, VERR_INTERNAL_ERROR_3);
     5783            AssertReturn(pFile, VERR_ISOMK_IPE_READ_FILE_DATA_3);
    50565784        } while ((offInFile = offUnsigned - pFile->offData) >= RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE));
    50575785    }
     
    51125840                break;
    51135841
     5842            case RTFSISOMAKERSRCTYPE_RR_SPILL:
     5843                Assert(pFile->cbData < UINT32_MAX);
     5844                if (   !(offInFile & ISO9660_SECTOR_OFFSET_MASK)
     5845                    && !(cbToRead & ISO9660_SECTOR_OFFSET_MASK)
     5846                    && cbToRead > 0)
     5847                    rc = rtFsIsoMakerOutFile_RockRidgeSpillReadSectors(pThis, pIsoMaker, pFile, (uint32_t)offInFile,
     5848                                                                       pbBuf, (uint32_t)cbToRead);
     5849                else
     5850                    rc = rtFsIsoMakerOutFile_RockRidgeSpillReadUnaligned(pThis, pIsoMaker, pFile, (uint32_t)offInFile,
     5851                                                                         pbBuf, (uint32_t)cbToRead);
     5852                break;
     5853
    51145854            default:
    5115                 AssertFailedReturn(VERR_INTERNAL_ERROR_5);
     5855                AssertFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE);
    51165856        }
    51175857        if (RT_FAILURE(rc))
     
    53196059 *
    53206060 * @returns Number of bytes copied into the buffer (pName->cbDirRec).
    5321  * @param   pName       The namespace node.
    5322  * @param   fUnicode    Set if the name should be translated to big endian
    5323  *                      UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace.
    5324  * @param   pbBuf       The buffer.  This is at least pName->cbDirRec bytes big
    5325  *                      (i.e. at most 256 bytes).
    5326  */
    5327 static uint32_t rtFsIsoMakerOutFile_GenerateDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf)
     6061 * @param   pName           The namespace node.
     6062 * @param   fUnicode        Set if the name should be translated to big endian
     6063 *                          UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace.
     6064 * @param   pbBuf           The buffer.  This is at least pName->cbDirRec bytes
     6065 *                          big (i.e. at most 256 bytes).
     6066 * @param   pFinalizedDirs  The finalized directory data for the namespace.
     6067 */
     6068static uint32_t rtFsIsoMakerOutFile_GenerateDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf,
     6069                                                   PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs)
    53286070{
    53296071    /*
     
    53926134     * Rock ridge fields if enabled.
    53936135     */
    5394     /** @todo rock ridge. */
     6136    if (pName->cbRockInDirRec > 0)
     6137    {
     6138        uint8_t *pbSys = (uint8_t *)&pDirRec->achFileId[pName->cbNameInDirRec + !(pName->cbNameInDirRec & 1)];
     6139        size_t   cbSys = &pbBuf[pName->cbDirRec] - pbSys;
     6140        Assert(cbSys >= pName->cbRockInDirRec);
     6141        if (cbSys > pName->cbRockInDirRec)
     6142            RT_BZERO(&pbSys[pName->cbRockInDirRec], cbSys - pName->cbRockInDirRec);
     6143        if (pName->cbRockSpill == 0)
     6144            rtFsIosMakerOutFile_GenerateRockRidge(pName, pbSys, cbSys, false /*fInSpill*/);
     6145        else
     6146        {
     6147            /* Maybe emit SP and RR entry, before emitting the CE entry. */
     6148            if (pName->pParent == NULL)
     6149            {
     6150                PISO9660SUSPSP pSP = (PISO9660SUSPSP)pbSys;
     6151                pSP->Hdr.bSig1     = ISO9660SUSPSP_SIG1;
     6152                pSP->Hdr.bSig2     = ISO9660SUSPSP_SIG2;
     6153                pSP->Hdr.cbEntry   = ISO9660SUSPSP_LEN;
     6154                pSP->Hdr.bVersion  = ISO9660SUSPSP_VER;
     6155                pSP->bCheck1       = ISO9660SUSPSP_CHECK1;
     6156                pSP->bCheck2       = ISO9660SUSPSP_CHECK2;
     6157                pSP->cbSkip        = 0;
     6158                pbSys += sizeof(*pSP);
     6159                cbSys -= sizeof(*pSP);
     6160            }
     6161            if (pName->fRockNeedRRInDirRec)
     6162            {
     6163                PISO9660RRIPRR pRR = (PISO9660RRIPRR)pbSys;
     6164                pRR->Hdr.bSig1     = ISO9660RRIPRR_SIG1;
     6165                pRR->Hdr.bSig2     = ISO9660RRIPRR_SIG2;
     6166                pRR->Hdr.cbEntry   = ISO9660RRIPRR_LEN;
     6167                pRR->Hdr.bVersion  = ISO9660RRIPRR_VER;
     6168                pRR->fFlags        = pName->fRockEntries;
     6169                pbSys += sizeof(*pRR);
     6170                cbSys -= sizeof(*pRR);
     6171            }
     6172            PISO9660SUSPCE pCE = (PISO9660SUSPCE)pbSys;
     6173            pCE->Hdr.bSig1     = ISO9660SUSPCE_SIG1;
     6174            pCE->Hdr.bSig2     = ISO9660SUSPCE_SIG2;
     6175            pCE->Hdr.cbEntry   = ISO9660SUSPCE_LEN;
     6176            pCE->Hdr.bVersion  = ISO9660SUSPCE_VER;
     6177            uint64_t offData = pFinalizedDirs->pRRSpillFile->offData + pName->offRockSpill;
     6178            pCE->offBlock.be   = RT_H2BE_U32((uint32_t)(offData / ISO9660_SECTOR_SIZE));
     6179            pCE->offBlock.le   = RT_H2LE_U32((uint32_t)(offData / ISO9660_SECTOR_SIZE));
     6180            pCE->offData.be    = RT_H2BE_U32((uint32_t)(offData & ISO9660_SECTOR_OFFSET_MASK));
     6181            pCE->offData.le    = RT_H2LE_U32((uint32_t)(offData & ISO9660_SECTOR_OFFSET_MASK));
     6182            pCE->cbData.be     = RT_H2BE_U32((uint32_t)pName->cbRockSpill);
     6183            pCE->cbData.le     = RT_H2LE_U32((uint32_t)pName->cbRockSpill);
     6184            Assert(cbSys >= sizeof(*pCE));
     6185        }
     6186    }
    53956187
    53966188    return pName->cbDirRec;
     
    54026194 *
    54036195 * @returns Number of bytes copied into the buffer.
    5404  * @param   pName       The namespace node.
    5405  * @param   fUnicode    Set if the name should be translated to big endian
    5406  *                      UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace.
    5407  * @param   pbBuf       The buffer.  This is at least pName->cbDirRecTotal bytes
    5408  *                      big.
    5409  */
    5410 static uint32_t rtFsIsoMakerOutFile_GenerateDirRecDirect(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf)
     6196 * @param   pName           The namespace node.
     6197 * @param   fUnicode        Set if the name should be translated to big endian
     6198 *                          UTF-16BE / UCS-2BE, i.e. we're in the joliet namespace.
     6199 * @param   pbBuf           The buffer.  This is at least pName->cbDirRecTotal
     6200 *                          bytes big.
     6201 * @param   pFinalizedDirs  The finalized directory data for the namespace.
     6202 */
     6203static uint32_t rtFsIsoMakerOutFile_GenerateDirRecDirect(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t *pbBuf,
     6204                                                         PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs)
    54116205{
    54126206    /*
    54136207     * Normally there is just a single record without any zero padding.
    54146208     */
    5415     uint32_t cbReturn = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf);
     6209    uint32_t cbReturn = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf, pFinalizedDirs);
    54166210    if (RT_LIKELY(pName->cbDirRecTotal == cbReturn))
    54176211        return cbReturn;
     
    54706264 *
    54716265 * @returns Number of bytes copied into the buffer.
    5472  * @param   pName       The namespace node.
    5473  * @param   fUnicode    Set if the name should be translated to big endian
    5474  *                      UTF-16 / UCS-2, i.e. we're in the joliet namespace.
    5475  * @param   off         The offset into the directory record.
    5476  * @param   pbBuf       The buffer.
    5477  * @param   cbBuf       The buffer size.
     6266 * @param   pName           The namespace node.
     6267 * @param   fUnicode        Set if the name should be translated to big endian
     6268 *                          UTF-16 / UCS-2, i.e. we're in the joliet namespace.
     6269 * @param   off             The offset into the directory record.
     6270 * @param   pbBuf           The buffer.
     6271 * @param   cbBuf           The buffer size.
     6272 * @param   pFinalizedDirs  The finalized directory data for the namespace.
    54786273 */
    54796274static uint32_t rtFsIsoMakerOutFile_GenerateDirRecPartial(PRTFSISOMAKERNAME pName, bool fUnicode,
    5480                                                           uint32_t off, uint8_t *pbBuf, size_t cbBuf)
     6275                                                          uint32_t off, uint8_t *pbBuf, size_t cbBuf,
     6276                                                          PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs)
    54816277{
    54826278    Assert(off < pName->cbDirRecTotal);
     
    54886284    uint8_t abTmpBuf[256];
    54896285    Assert(pName->cbDirRec <= sizeof(abTmpBuf));
    5490     uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf);
     6286    uint32_t const cbOne = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf, pFinalizedDirs);
    54916287    Assert(cbOne == pName->cbDirRec);
    54926288    if (cbOne == pName->cbDirRecTotal)
     
    55886384 *
    55896385 * @returns Number of bytes copied into the buffer.
    5590  * @param   pName       The directory namespace node.
    5591  * @param   fUnicode    Set if the name should be translated to big endian
    5592  *                      UTF-16 / UCS-2, i.e. we're in the joliet namespace.
    5593  * @param   bDirId      The directory ID (0x00 or 0x01).
    5594  * @param   off         The offset into the directory record.
    5595  * @param   pbBuf       The buffer.
    5596  * @param   cbBuf       The buffer size.
     6386 * @param   pName           The directory namespace node.
     6387 * @param   fUnicode        Set if the name should be translated to big endian
     6388 *                          UTF-16 / UCS-2, i.e. we're in the joliet namespace.
     6389 * @param   bDirId          The directory ID (0x00 or 0x01).
     6390 * @param   off             The offset into the directory record.
     6391 * @param   pbBuf           The buffer.
     6392 * @param   cbBuf           The buffer size.
     6393 * @param   pFinalizedDirs  The finalized directory data for the namespace.
    55976394 */
    55986395static uint32_t rtFsIsoMakerOutFile_GenerateSpecialDirRec(PRTFSISOMAKERNAME pName, bool fUnicode, uint8_t bDirId,
    5599                                                           uint32_t off, uint8_t *pbBuf, size_t cbBuf)
     6396                                                          uint32_t off, uint8_t *pbBuf, size_t cbBuf,
     6397                                                          PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs)
    56006398{
    56016399    Assert(off < pName->cbDirRec);
     
    56056403    uint8_t abTmpBuf[256];
    56066404    Assert(off < pName->cbDirRec);
    5607     size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf);
     6405    size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf, pFinalizedDirs);
    56086406    Assert(cbToCopy == pName->cbDirRec);
    56096407
     
    57076505            if (offInDir < pDir->cbDirRec00)
    57086506            {
    5709                 uint32_t cbCopied = rtFsIsoMakerOutFile_GenerateSpecialDirRec(pDirName, fUnicode, 0, offInDir, pbBuf, cbBuf);
     6507                uint32_t cbCopied = rtFsIsoMakerOutFile_GenerateSpecialDirRec(pDirName, fUnicode, 0, offInDir,
     6508                                                                              pbBuf, cbBuf, pFinalizedDirs);
    57106509                cbDone   += cbCopied;
    57116510                offInDir += cbCopied;
     
    57186517            {
    57196518                uint32_t cbCopied = rtFsIsoMakerOutFile_GenerateSpecialDirRec(pParentName, fUnicode, 1,
    5720                                                                               offInDir - pDir->cbDirRec00, pbBuf, cbBuf);
     6519                                                                              offInDir - pDir->cbDirRec00,
     6520                                                                              pbBuf, cbBuf, pFinalizedDirs);
    57216521                cbDone   += cbCopied;
    57226522                offInDir += cbCopied;
     
    57556555            if (   offInDir == pChild->offDirRec
    57566556                && cbBuf    >= pChild->cbDirRecTotal)
    5757                 cbCopied = rtFsIsoMakerOutFile_GenerateDirRecDirect(pChild, fUnicode, pbBuf);
     6557                cbCopied = rtFsIsoMakerOutFile_GenerateDirRecDirect(pChild, fUnicode, pbBuf, pFinalizedDirs);
    57586558            else
    5759                 cbCopied = rtFsIsoMakerOutFile_GenerateDirRecPartial(pChild, fUnicode, offInDir - pChild->offDirRec, pbBuf, cbBuf);
     6559                cbCopied = rtFsIsoMakerOutFile_GenerateDirRecPartial(pChild, fUnicode, offInDir - pChild->offDirRec,
     6560                                                                     pbBuf, cbBuf, pFinalizedDirs);
    57606561
    57616562            cbDone   += cbCopied;
     
    59046705            cbDone = rtFsIsoMakerOutFile_ReadDirStructures(&pThis->pDirHintPrimaryIso, &pIsoMaker->PrimaryIso,
    59056706                                                           &pIsoMaker->PrimaryIsoDirs, offUnsigned, pbBuf, cbBuf);
    5906         /** @todo Insert El Torito stuff here? Probably okay to let it be in the file
    5907          *        area, right? */
    59086707        /*
    59096708         * Volume descriptors.
     
    60566855
    60576856        default:
    6058             return VERR_INTERNAL_ERROR_5;
     6857            return VERR_INVALID_PARAMETER;
    60596858    }
    60606859
     
    61696968        pFileData->pDirHintPrimaryIso = NULL;
    61706969        pFileData->pDirHintJoliet     = NULL;
     6970        pFileData->iChildPrimaryIso   = UINT32_MAX;
     6971        pFileData->iChildJoliet       = UINT32_MAX;
    61716972        *phVfsFile = hVfsFile;
    61726973        return VINF_SUCCESS;
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