VirtualBox

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


Ignore:
Timestamp:
Jun 13, 2017 7:10:51 PM (8 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code.

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

Legend:

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

    r67370 r67381  
    5757#define RTFSISOMAKER_ASSER_VALID_HANDLE_RET_EX(a_pThis, a_rcRet) \
    5858    do { AssertPtrReturn(a_pThis, a_rcRet); \
    59          AssertPtrReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, a_rcRet); \
     59         AssertReturn((a_pThis)->uMagic == RTFSISOMAKERINT_MAGIC, a_rcRet); \
    6060    } while (0)
    6161
     
    525525     * RTFSISOMAKERSRCTYPE_TRANS_TBL file. */
    526526    RTVFSFILE               hVfsSrcFile;
    527     /** Current directory hint. */
    528     PRTFSISOMAKERNAMEDIR    pDirHint;
     527    /** Current directory hint for the primary ISO namespace. */
     528    PRTFSISOMAKERNAMEDIR    pDirHintPrimaryIso;
     529    /** Current directory hint for the joliet namespace. */
     530    PRTFSISOMAKERNAMEDIR    pDirHintJoliet;
    529531} RTFSISOMAKEROUTPUTFILE;
    530532/** Pointer to the instance data of an ISO maker output file. */
     
    634636     * Create the instance with defaults.
    635637     */
     638    int              rc;
    636639    PRTFSISOMAKERINT pThis = (PRTFSISOMAKERINT)RTMemAllocZ(sizeof(*pThis));
    637640    if (pThis)
     
    741744
    742745        RTTimeNow(&pThis->ImageCreationTime);
    743         *phIsoMaker = pThis;
    744         return VINF_SUCCESS;
    745     }
    746     return VERR_NO_MEMORY;
     746
     747        /*
     748         * Add the root directory node with idObj == 0.
     749         */
     750        PRTFSISOMAKERDIR pDirRoot;
     751        rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pDirRoot);
     752        if (RT_SUCCESS(rc))
     753        {
     754            *phIsoMaker = pThis;
     755            return VINF_SUCCESS;
     756        }
     757
     758        RTMemFree(pThis);
     759    }
     760    else
     761        rc = VERR_NO_MEMORY;
     762    return rc;
    747763}
    748764
     
    15911607                pszDst[cchSrc] = '\0';
    15921608                *pcchDst     = cchSrc;
    1593                 *pcbInDirRec = RTStrCalcUtf16Len(pszDst);
     1609                *pcbInDirRec = RTStrCalcUtf16Len(pszDst) * sizeof(RTUTF16);
    15941610                return VINF_SUCCESS;
    15951611            }
     
    16111627        *pcchDst     = 0;
    16121628        *pcbInDirRec = 0;
    1613         AssertReturn(pParent, VERR_INTERNAL_ERROR_3);
     1629        AssertReturn(!pParent, VERR_INTERNAL_ERROR_3);
    16141630        return VINF_SUCCESS;
    16151631    }
     
    17491765            pName->cchRockRidgeNm       = (uint16_t)cchSpec;
    17501766            pName->cchTransNm           = (uint16_t)cchSpec;
    1751             pName->uDepth               = pParent->uDepth + 1;
     1767            pName->uDepth               = pParent ? pParent->uDepth + 1 : 0;
    17521768            pName->fRockRidgeNmAlloced  = false;
    17531769            pName->fTransNmAlloced      = false;
     
    18571873    if (!pParent)
    18581874    {
    1859         PRTFSISOMAKERDIR pDir;
    1860         if (pThis->cObjects == 0)
    1861         {
    1862             rc = rtFsIsoMakerAddUnnamedDirWorker(pThis, &pDir);
    1863             AssertRCReturn(rc, rc);
    1864         }
    1865         else
    1866         {
    1867             pDir = RTListGetFirst(&pThis->ObjectHead, RTFSISOMAKERDIR, Core.Entry);
     1875        PRTFSISOMAKERDIR pDir = RTListGetFirst(&pThis->ObjectHead, RTFSISOMAKERDIR, Core.Entry);
    18681876#ifdef RT_STRICT
    1869             Assert(pDir);
    1870             Assert(pDir->Core.idxObj == 0);
    1871             Assert(pDir->Core.enmType == RTFSISOMAKEROBJTYPE_DIR);
    1872             Assert(*rtFsIsoMakerObjGetNameForNamespace(&pDir->Core, pNamespace) == NULL);
     1877        Assert(pDir);
     1878        Assert(pDir->Core.idxObj == 0);
     1879        Assert(pDir->Core.enmType == RTFSISOMAKEROBJTYPE_DIR);
     1880        Assert(*rtFsIsoMakerObjGetNameForNamespace(&pDir->Core, pNamespace) == NULL);
    18731881#endif
    1874         }
    18751882
    18761883        rc = rtFsIsoMakerObjSetName(pThis, pNamespace, &pDir->Core, NULL /*pParent*/, "", 0, &pParent);
     
    18901897        char ch;
    18911898        size_t cchComponent = 0;
    1892         while ((ch = pszPath[cchComponent]) != '\0' && RTPATH_IS_SLASH(ch))
     1899        while ((ch = pszPath[cchComponent]) != '\0' && !RTPATH_IS_SLASH(ch))
    18931900            cchComponent++;
    18941901        AssertReturn(cchComponent > 0, VERR_INTERNAL_ERROR_4);
     
    25102517    if (RT_SUCCESS(rc))
    25112518    {
    2512         pFile->cbData       = pObjInfo->cbObject;
     2519        pFile->cbData       = pObjInfo ? pObjInfo->cbObject : 0;
    25132520        pThis->cbData += RT_ALIGN_64(pFile->cbData, RTFSISOMAKER_SECTOR_SIZE);
    25142521        pFile->offData      = UINT64_MAX;
     
    28882895         */
    28892896        PRTFSISOMAKERNAMEDIR pCurDir;
    2890         RTListForEach(&pThis->PrimaryIsoDirs.FinalizedDirs, pCurDir, RTFSISOMAKERNAMEDIR, FinalizedEntry)
     2897        RTListForEach(&pFinalizedDirs->FinalizedDirs, pCurDir, RTFSISOMAKERNAMEDIR, FinalizedEntry)
    28912898        {
    28922899            PRTFSISOMAKERNAME pCurName    = pCurDir->pName;
     
    30103017static int rtFsIsoMakerFinalizeData(PRTFSISOMAKERINT pThis, uint64_t *poffData)
    30113018{
     3019    pThis->offFirstFile = *poffData;
     3020
    30123021    /*
    30133022     * We currently does not have any ordering prioritizing implemented, so we
     
    33503359    pPrimary->RootDir.DirRec.bInterleaveGapSize = 0;
    33513360    pPrimary->RootDir.DirRec.VolumeSeqNo.be     = RT_H2BE_U16_C(1);
    3352     pPrimary->RootDir.DirRec.VolumeSeqNo.le     = RT_H2BE_U16_C(1);
     3361    pPrimary->RootDir.DirRec.VolumeSeqNo.le     = RT_H2LE_U16_C(1);
    33533362    pPrimary->RootDir.DirRec.bFileIdLength      = 1;
    33543363    pPrimary->RootDir.DirRec.achFileId[1]       = 0x00;
     
    33763385        pJoliet->RootDir.DirRec.bInterleaveGapSize = 0;
    33773386        pJoliet->RootDir.DirRec.VolumeSeqNo.be     = RT_H2BE_U16_C(1);
    3378         pJoliet->RootDir.DirRec.VolumeSeqNo.le     = RT_H2BE_U16_C(1);
     3387        pJoliet->RootDir.DirRec.VolumeSeqNo.le     = RT_H2LE_U16_C(1);
    33793388        pJoliet->RootDir.DirRec.bFileIdLength      = 1;
    33803389        pJoliet->RootDir.DirRec.achFileId[1]       = 0x00;
     
    34033412    if (RT_FAILURE(rc))
    34043413        return rc;
     3414    AssertReturn(pThis->cObjects > 0, VERR_NO_DATA);
     3415    AssertReturn(pThis->PrimaryIso.pRoot || pThis->PrimaryIso.uLevel == 0, VERR_NO_DATA);
     3416    AssertReturn(pThis->Joliet.pRoot     || pThis->Joliet.uLevel     == 0, VERR_NO_DATA);
     3417
    34053418    rc = rtFsIsoMakerFinalizePrepVolumeDescriptors(pThis);
    34063419    if (RT_FAILURE(rc))
     
    37883801 *
    37893802 * @returns Number of bytes written to the buffer.
    3790  * @param   pThis           The instance data for the VFS file.  We use this to
    3791  *                          keep hints about where we are and we which source
    3792  *                          file we've opened/created.
     3803 * @param   ppDirHint       Pointer to the directory hint for the namespace.
    37933804 * @param   pFinalizedDirs  The finalized directory data for the namespace.
    37943805 * @param   fUnicode        Set if the name should be translated to big endian
     
    38003811 * @param   cbBuf           The buffer size.
    38013812 */
    3802 static size_t rtFsIsoMakerOutFile_ReadPathTable(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs,
     3813static size_t rtFsIsoMakerOutFile_ReadPathTable(PRTFSISOMAKERNAMEDIR *ppDirHint, PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs,
    38033814                                                bool fUnicode, bool fLittleEndian, uint32_t offInTable,
    38043815                                                uint8_t *pbBuf, size_t cbBuf)
     
    38073818     * Figure out which directory to start with.  We keep a hint in the instance.
    38083819     */
    3809     PRTFSISOMAKERNAMEDIR pDir = pThis->pDirHint;
     3820    PRTFSISOMAKERNAMEDIR pDir = *ppDirHint;
    38103821    if (!pDir)
    38113822    {
     
    38623873     * Update the hint.
    38633874     */
    3864     pThis->pDirHint = pDir;
     3875    *ppDirHint = pDir;
    38653876
    38663877    return cbDone;
     
    39173928    pDirRec->bInterleaveGapSize     = 0;
    39183929    pDirRec->VolumeSeqNo.be         = RT_H2BE_U16_C(1);
    3919     pDirRec->VolumeSeqNo.le         = RT_H2BE_U16_C(1);
     3930    pDirRec->VolumeSeqNo.le         = RT_H2LE_U16_C(1);
    39203931    pDirRec->bFileIdLength          = pName->cbNameInDirRec;
    39213932
     
    39974008    /* Generate a regular directory record. */
    39984009    uint8_t abTmpBuf[256];
    3999     size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, pbBuf);
     4010    size_t cbToCopy = rtFsIsoMakerOutFile_GenerateDirRec(pName, fUnicode, abTmpBuf);
    40004011
    40014012    /* Replace the filename part. */
     
    40284039 *
    40294040 * @returns Number of bytes copied into @a pbBuf.
    4030  * @param   pThis           The instance data for the VFS file.  We use this to
    4031  *                          keep hints about where we are and we which source
    4032  *                          file we've opened/created.
     4041 * @param   ppDirHint       Pointer to the directory hint for the namespace.
    40334042 * @param   pIsoMaker       The ISO maker instance.
    40344043 * @param   pFinalizedDirs  The finalized directory data for the namespace.
     
    40394048 * @param   cbBuf           How much to read.
    40404049 */
    4041 static size_t rtFsIsoMakerOutFile_ReadDirRecords(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs,
     4050static size_t rtFsIsoMakerOutFile_ReadDirRecords(PRTFSISOMAKERNAMEDIR *ppDirHint, PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs,
    40424051                                                 bool fUnicode, uint64_t offUnsigned, uint8_t *pbBuf, size_t cbBuf)
    40434052{
     
    40464055     */
    40474056    uint64_t             offInDir64;
    4048     PRTFSISOMAKERNAMEDIR pDir = pThis->pDirHint;
     4057    PRTFSISOMAKERNAMEDIR pDir = *ppDirHint;
    40494058    if (!pDir)
    40504059    {
     
    40784087     * Update the hint.
    40794088     */
    4080     pThis->pDirHint = pDir;
     4089    *ppDirHint = pDir;
    40814090
    40824091    /*
     
    41864195 *
    41874196 * @returns Number of bytes copied into @a pbBuf.
    4188  * @param   pThis           The instance data for the VFS file.  We use this to
    4189  *                          keep hints about where we are and we which source
    4190  *                          file we've opened/created.
     4197 * @param   ppDirHint       Pointer to the directory hint for the namespace.
    41914198 * @param   pIsoMaker       The ISO maker instance.
    41924199 * @param   pNamespace      The namespace.
     
    41964203 * @param   cbBuf           How much to read.
    41974204 */
    4198 static size_t rtFsIsoMakerOutFile_ReadDirStructures(PRTFSISOMAKEROUTPUTFILE pThis, PRTFSISOMAKERNAMESPACE pNamespace,
     4205static size_t rtFsIsoMakerOutFile_ReadDirStructures(PRTFSISOMAKERNAMEDIR *ppDirHint, PRTFSISOMAKERNAMESPACE pNamespace,
    41994206                                                    PRTFSISOMAKERFINALIZEDDIRS pFinalizedDirs,
    42004207                                                    uint64_t offUnsigned, uint8_t *pbBuf, size_t cbBuf)
    42014208{
    42024209    if (offUnsigned < pFinalizedDirs->offPathTableL)
    4203         return rtFsIsoMakerOutFile_ReadDirRecords(pThis, pFinalizedDirs, pNamespace->fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET,
     4210        return rtFsIsoMakerOutFile_ReadDirRecords(ppDirHint, pFinalizedDirs,
     4211                                                  pNamespace->fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET,
    42044212                                                  offUnsigned, pbBuf, cbBuf);
    42054213
    42064214    uint64_t offInTable;
    42074215    if ((offInTable = offUnsigned - pFinalizedDirs->offPathTableL) < pFinalizedDirs->cbPathTable)
    4208         return rtFsIsoMakerOutFile_ReadPathTable(pThis, pFinalizedDirs, pNamespace->fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET,
     4216        return rtFsIsoMakerOutFile_ReadPathTable(ppDirHint, pFinalizedDirs,
     4217                                                 pNamespace->fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET,
    42094218                                                 true /*fLittleEndian*/, (uint32_t)offInTable, pbBuf, cbBuf);
    42104219
    42114220    if ((offInTable = offUnsigned - pFinalizedDirs->offPathTableM) < pFinalizedDirs->cbPathTable)
    4212         return rtFsIsoMakerOutFile_ReadPathTable(pThis, pFinalizedDirs, pNamespace->fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET,
     4221        return rtFsIsoMakerOutFile_ReadPathTable(ppDirHint, pFinalizedDirs,
     4222                                                 pNamespace->fNamespace == RTFSISOMAKER_NAMESPACE_JOLIET,
    42134223                                                 false /*fLittleEndian*/, (uint32_t)offInTable, pbBuf, cbBuf);
    42144224
     
    42874297        else if (   offUnsigned >= pIsoMaker->JolietDirs.offDirs
    42884298                 && pIsoMaker->JolietDirs.offDirs < pIsoMaker->JolietDirs.offPathTableL)
    4289             cbDone = rtFsIsoMakerOutFile_ReadDirStructures(pThis, &pIsoMaker->Joliet, &pIsoMaker->JolietDirs,
     4299            cbDone = rtFsIsoMakerOutFile_ReadDirStructures(&pThis->pDirHintJoliet, &pIsoMaker->Joliet, &pIsoMaker->JolietDirs,
    42904300                                                           offUnsigned, pbBuf, cbBuf);
    42914301        /*
     
    42934303         */
    42944304        else if (offUnsigned >= pIsoMaker->PrimaryIsoDirs.offDirs)
    4295             cbDone = rtFsIsoMakerOutFile_ReadDirStructures(pThis, &pIsoMaker->PrimaryIso, &pIsoMaker->PrimaryIsoDirs,
    4296                                                            offUnsigned, pbBuf, cbBuf);
     4305            cbDone = rtFsIsoMakerOutFile_ReadDirStructures(&pThis->pDirHintPrimaryIso, &pIsoMaker->PrimaryIso,
     4306                                                           &pIsoMaker->PrimaryIsoDirs, offUnsigned, pbBuf, cbBuf);
    42974307        /** @todo Insert El Torito stuff here? Probably okay to let it be in the file
    42984308         *        area, right? */
     
    45544564    if (RT_SUCCESS(rc))
    45554565    {
    4556         pFileData->pIsoMaker   = pThis;
    4557         pFileData->offCurPos   = 0;
    4558         pFileData->pFileHint   = NULL;
    4559         pFileData->hVfsSrcFile = NIL_RTVFSFILE;
    4560         pFileData->pDirHint    = NULL;
     4566        pFileData->pIsoMaker          = pThis;
     4567        pFileData->offCurPos          = 0;
     4568        pFileData->pFileHint          = NULL;
     4569        pFileData->hVfsSrcFile        = NIL_RTVFSFILE;
     4570        pFileData->pDirHintPrimaryIso = NULL;
     4571        pFileData->pDirHintJoliet     = NULL;
     4572        *phVfsFile = hVfsFile;
    45614573        return VINF_SUCCESS;
    45624574    }
  • trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp

    r67370 r67381  
    5757/** @name Name specifiers
    5858 * @{ */
    59 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO                 RT_BIT_32(0)
    60 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO_ROCK_RIDGE      RT_BIT_32(1)
    61 #define RTFSISOMAKERCMDNAME_PRIMARY_ISO_TRANS_TBL       RT_BIT_32(2)
    62 #define RTFSISOMAKERCMDNAME_JOLIET                      RT_BIT_32(3)
    63 #define RTFSISOMAKERCMDNAME_JOLIET_ROCK_RIDGE           RT_BIT_32(4)
    64 #define RTFSISOMAKERCMDNAME_JOLIET_TRANS_TBL            RT_BIT_32(5)
    65 #define RTFSISOMAKERCMDNAME_UDF                         RT_BIT_32(6)
    66 #define RTFSISOMAKERCMDNAME_UDF_TRANS_TBL               RT_BIT_32(7)
    67 #define RTFSISOMAKERCMDNAME_HFS                         RT_BIT_32(8)
    68 #define RTFSISOMAKERCMDNAME_HFS_TRANS_TBL               RT_BIT_32(9)
     59#define RTFSISOMAKERCMDNAME_PRIMARY_ISO                 RTFSISOMAKER_NAMESPACE_ISO_9660
     60#define RTFSISOMAKERCMDNAME_JOLIET                      RTFSISOMAKER_NAMESPACE_JOLIET
     61#define RTFSISOMAKERCMDNAME_UDF                         RTFSISOMAKER_NAMESPACE_UDF
     62#define RTFSISOMAKERCMDNAME_HFS                         RTFSISOMAKER_NAMESPACE_HFS
     63
     64#define RTFSISOMAKERCMDNAME_PRIMARY_ISO_ROCK_RIDGE      RT_BIT_32(16)
     65#define RTFSISOMAKERCMDNAME_JOLIET_ROCK_RIDGE           RT_BIT_32(17)
     66
     67#define RTFSISOMAKERCMDNAME_JOLIET_TRANS_TBL            RT_BIT_32(20)
     68#define RTFSISOMAKERCMDNAME_PRIMARY_ISO_TRANS_TBL       RT_BIT_32(21)
     69#define RTFSISOMAKERCMDNAME_UDF_TRANS_TBL               RT_BIT_32(22)
     70#define RTFSISOMAKERCMDNAME_HFS_TRANS_TBL               RT_BIT_32(23)
    6971
    7072#define RTFSISOMAKERCMDNAME_MAJOR_MASK \
    7173        (RTFSISOMAKERCMDNAME_PRIMARY_ISO | RTFSISOMAKERCMDNAME_JOLIET | RTFSISOMAKERCMDNAME_UDF | RTFSISOMAKERCMDNAME_HFS)
     74
    7275#define RTFSISOMAKERCMDNAME_MINOR_MASK \
    7376        ( RTFSISOMAKERCMDNAME_PRIMARY_ISO_ROCK_RIDGE | RTFSISOMAKERCMDNAME_PRIMARY_ISO_TRANS_TBL \
     
    7578        | RTFSISOMAKERCMDNAME_UDF_TRANS_TBL \
    7679        | RTFSISOMAKERCMDNAME_HFS_TRANS_TBL)
     80AssertCompile((RTFSISOMAKERCMDNAME_MAJOR_MASK & RTFSISOMAKERCMDNAME_MINOR_MASK) == 0);
    7781/** @} */
     82
    7883
    7984/*********************************************************************************************************************************
     
    285290/** Pointer to a parsed name. */
    286291typedef RTFSISOMAKERCMDPARSEDNAME *PRTFSISOMAKERCMDPARSEDNAME;
     292/** Pointer to a const parsed name. */
     293typedef RTFSISOMAKERCMDPARSEDNAME const *PCRTFSISOMAKERCMDPARSEDNAME;
    287294
    288295
     
    900907
    901908/**
     909 * Adds a file.
     910 *
     911 * @returns IPRT status code.
     912 * @param   pOpts               The ISO maker command instance.
     913 * @param   pszSrc              The path to the source file.
     914 * @param   paParsedNames       Array of parsed names, there are
     915 *                              pOpts->cNameSpecifiers entries in the array.
     916 */
     917static int rtFsIsoMakerCmdAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMAKERCMDPARSEDNAME paParsedNames)
     918{
     919    uint32_t idxObj;
     920    int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj);
     921    if (RT_SUCCESS(rc))
     922    {
     923        pOpts->cItemsAdded++;
     924
     925        for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
     926            if (paParsedNames[i].cchPath > 0)
     927            {
     928                if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)
     929                {
     930                    rc = RTFsIsoMakerObjSetPath(pOpts->hIsoMaker, idxObj,
     931                                                paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
     932                                                paParsedNames[i].szPath);
     933                    if (RT_FAILURE(rc))
     934                    {
     935                        rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting name '%s' on '%s': %Rrc",
     936                                                    paParsedNames[i].szPath, pszSrc, rc);
     937                        break;
     938                    }
     939                }
     940                if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK)
     941                {
     942                    /** @todo add APIs for this.   */
     943                }
     944            }
     945    }
     946    else
     947        rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc);
     948    return rc;
     949}
     950
     951
     952/**
    902953 * Processes a non-option argument.
    903954 *
    904  * @returns
    905  * @param   pOpts               .
    906  * @param   pszSpec             .
     955 * @returns IPRT status code.
     956 * @param   pOpts               The ISO maker command instance.
     957 * @param   pszSpec             The specification of what to add.
    907958 */
    908959static int rtFsIsoMakerCmdAddSomething(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec)
    909960{
    910961    const char * const pszSpecIn = pszSpec;
     962    enum { kSpecialSrc_Normal, kSpecialSrc_Remove, kSpecialSrc_MustRemove } enmSpecialSrc = kSpecialSrc_Normal;
    911963
    912964    /*
     
    917969    for (;;)
    918970    {
    919         const char *pszEqual = strchr(pszSpec, '=');
    920         size_t      cchName  = pszEqual ? pszEqual - pszSpec : strlen(pszSpec);
    921         if (cchName >= sizeof(aParsedNames[cParsedNames].szPath))
     971        const char *pszEqual   = strchr(pszSpec, '=');
     972        size_t      cchName    = pszEqual ? pszEqual - pszSpec : strlen(pszSpec);
     973        bool        fNeedSlash = pszEqual && !RTPATH_IS_SLASH(*pszSpec) && cchName > 0;
     974        if (cchName + fNeedSlash >= sizeof(aParsedNames[cParsedNames].szPath))
    922975            return rtFsIsoMakerCmdSyntaxError(pOpts, "name #%u (0-based) is too long: %s", cParsedNames, pszSpecIn);
    923976        if (cParsedNames >= pOpts->cNameSpecifiers + 1)
    924977            return rtFsIsoMakerCmdSyntaxError(pOpts, "too many names specified (max %u + source): %s",
    925978                                              pOpts->cNameSpecifiers,  pszSpecIn);
    926         memcpy(aParsedNames[cParsedNames].szPath, pszSpec, cchName);
     979        if (!fNeedSlash)
     980            memcpy(aParsedNames[cParsedNames].szPath, pszSpec, cchName);
     981        else
     982        {
     983            memcpy(&aParsedNames[cParsedNames].szPath[1], pszSpec, cchName);
     984            aParsedNames[cParsedNames].szPath[0] = RTPATH_SLASH;
     985            cchName++;
     986        }
    927987        aParsedNames[cParsedNames].szPath[cchName] = '\0';
    928988        aParsedNames[cParsedNames].cchPath = (uint32_t)cchName;
    929989        cParsedNames++;
     990
    930991        if (!pszEqual)
    931992        {
    932993            if (!cchName)
    933994                return rtFsIsoMakerCmdSyntaxError(pOpts, "empty source file name: %s", pszSpecIn);
     995            if (cchName == 8 && strcmp(pszSpec, ":remove:") == 0)
     996                enmSpecialSrc = kSpecialSrc_Remove;
     997            else if (cchName == 13 && strcmp(pszSpec, ":must-remove:") == 0)
     998                enmSpecialSrc = kSpecialSrc_MustRemove;
    934999            break;
    9351000        }
     
    9441009        aParsedNames[pOpts->cNameSpecifiers] = aParsedNames[cParsedNames - 1];
    9451010        uint32_t iSrc = cParsedNames >= 2 ? cParsedNames - 2 : 0;
     1011
     1012        /* If the source is a input file name specifier, reduce it to something that starts with a slash. */
     1013        if (cParsedNames == 1)
     1014        {
     1015            if (RTVfsChainIsSpec(aParsedNames[iSrc].szPath))
     1016            {
     1017                char *pszFinalPath;
     1018                int rc = RTVfsChainQueryFinalPath(aParsedNames[iSrc].szPath, &pszFinalPath, NULL);
     1019                if (RT_FAILURE(rc))
     1020                    return rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTVfsChainQueryFinalPath failed with %Rrc on: %s", rc, pszSpecIn);
     1021                aParsedNames[iSrc].cchPath = (uint32_t)strlen(pszFinalPath);
     1022                if (RTPATH_IS_SLASH(*pszFinalPath))
     1023                    memcpy(aParsedNames[iSrc].szPath, pszFinalPath, aParsedNames[iSrc].cchPath + 1);
     1024                else
     1025                {
     1026                    memcpy(&aParsedNames[iSrc].szPath[1], pszFinalPath, aParsedNames[iSrc].cchPath + 1);
     1027                    aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;
     1028                    aParsedNames[iSrc].cchPath++;
     1029                }
     1030                RTStrFree(pszFinalPath);
     1031            }
     1032#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
     1033            else if (   RTPATH_IS_VOLSEP(aParsedNames[iSrc].szPath[1])
     1034                     && RT_C_IS_ALPHA(aParsedNames[iSrc].szPath[0]))
     1035            {
     1036                if (RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[2]))
     1037                {
     1038                    memmove(&aParsedNames[iSrc].szPath[0], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1);
     1039                    aParsedNames[iSrc].cchPath -= 2;
     1040                }
     1041                else
     1042                {
     1043                    memmove(&aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1);
     1044                    aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;
     1045                    aParsedNames[iSrc].cchPath  -= 1;
     1046                }
     1047            }
     1048#endif
     1049            else if (!RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[0]))
     1050            {
     1051                if (aParsedNames[iSrc].cchPath + 2 > sizeof(aParsedNames[iSrc].szPath))
     1052                    return rtFsIsoMakerCmdSyntaxError(pOpts, "name too long: %s", pszSpecIn);
     1053                memmove(&aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[0], aParsedNames[iSrc].cchPath + 1);
     1054                aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;
     1055                aParsedNames[iSrc].cchPath++;
     1056            }
     1057        }
     1058
    9461059        for (uint32_t iDst = cParsedNames; iDst < pOpts->cNameSpecifiers; iDst++)
    9471060            aParsedNames[iDst] = aParsedNames[iSrc];
     
    9491062    }
    9501063
    951     /* Copy the specifier flags. */
     1064    /*
     1065     * Copy the specifier flags and check that the paths all starts with slashes.
     1066     */
    9521067    for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
     1068    {
    9531069        aParsedNames[i].fNameSpecifiers = pOpts->afNameSpecifiers[i];
     1070        Assert(   aParsedNames[i].cchPath == 0
     1071               || RTPATH_IS_SLASH(aParsedNames[i].szPath[0]));
     1072    }
    9541073
    9551074    /*
    9561075     * Deal with special source filenames used to remove/change stuff.
    9571076     */
    958     const char * const pszSrc = aParsedNames[cParsedNames - 1].szPath;
    959     if (strcmp(pszSrc, ":remove:") == 0)
     1077    if (   enmSpecialSrc == kSpecialSrc_Remove
     1078        || enmSpecialSrc == kSpecialSrc_MustRemove)
    9601079    {
    961 
     1080        const char *pszFirstNm = NULL;
     1081        uint32_t    cRemoved   = 0;
     1082        for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
     1083            if (   aParsedNames[i].cchPath > 0
     1084                && (aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))
     1085            {
     1086                pszFirstNm = aParsedNames[i].szPath;
     1087                uint32_t idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker,
     1088                                                               aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
     1089                                                               aParsedNames[i].szPath);
     1090                if (idxObj != UINT32_MAX)
     1091                {
     1092                    int rc = RTFsIsoMakerObjRemove(pOpts->hIsoMaker, idxObj);
     1093                    if (RT_FAILURE(rc))
     1094                        return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpecIn, rc);
     1095                    cRemoved++;
     1096                }
     1097            }
     1098        if (   enmSpecialSrc == kSpecialSrc_MustRemove
     1099            && cRemoved == 0)
     1100            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpecIn);
    9621101    }
     1102    /*
     1103     * Add regular source.
     1104     */
    9631105    else
    9641106    {
    965         /*
    966          * Regular source.
    967          */
    968 
     1107        const char     *pszSrc = aParsedNames[cParsedNames - 1].szPath;
     1108        RTFSOBJINFO     ObjInfo;
     1109        uint32_t        offError;
     1110        RTERRINFOSTATIC ErrInfo;
     1111        int rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX,
     1112                                     RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo));
     1113        if (RT_FAILURE(rc))
     1114            return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error query info on '%s': %Rrc", pszSrc, rc);
     1115        if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
     1116            return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, aParsedNames);
     1117        if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
     1118            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpecIn);
     1119        if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
     1120            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpecIn);
     1121        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpecIn);
    9691122    }
    9701123
     
    9971150    Opts.pErrInfo               = pErrInfo;
    9981151    Opts.fVirtualImageMaker     = phVfsFile != NULL;
     1152    Opts.cNameSpecifiers        = 1;
     1153    Opts.afNameSpecifiers[0]    = RTFSISOMAKERCMDNAME_MAJOR_MASK;
     1154    Opts.fDstNamespaces         = RTFSISOMAKERCMDNAME_MAJOR_MASK;
    9991155    if (phVfsFile)
    10001156        *phVfsFile = NIL_RTVFSFILE;
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