VirtualBox

Ignore:
Timestamp:
Jun 13, 2017 7:10:51 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
116101
Message:

IPRT: More ISO maker code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.

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