VirtualBox

Ignore:
Timestamp:
Jun 16, 2017 1:14:39 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
116168
Message:

IPRT: More ISO maker code (booting related).

File:
1 edited

Legend:

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

    r67434 r67437  
    268268             * pszImageNameInIso is used (i.e. -b option) and we've delayed everything
    269269             * boot related till after all files have been added to the image. */
    270             uint32_t    idImage;
     270            uint32_t    idxImageObj;
    271271            /** Whether to insert boot info table into the image. */
    272272            bool        fInsertBootInfoTable;
    273273            /** Bootble or not.  Possible to make BIOS set up emulation w/o booting it. */
    274274            bool        fBootable;
    275             /** The media type (ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX) and flags
    276              * (ISO9660_ELTORITO_BOOT_MEDIA_F_XXX). */
     275            /** The media type (ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX). */
    277276            uint8_t     bBootMediaType;
    278277            /** File system / partition type. */
     
    332331    /** Number of boot catalog entries (aBootCatEntries). */
    333332    uint32_t                    cBootCatEntries;
    334     /** Number of boot catalog entries we're done with (i.e. added to hIsoMaker). */
    335     uint32_t                    cBootCatEntriesDone;
    336333    /** Boot catalog entries. */
    337334    RTFSISOMKCMDELTORITOENTRY   aBootCatEntries[64];
     
    346343
    347344/**
    348  * Parsed name.
    349  */
    350 typedef struct RTFSISOMAKERCMDPARSEDNAME
     345 * One parsed name.
     346 */
     347typedef struct RTFSISOMKCMDPARSEDNAME
    351348{
    352349    /** Copy of the corresponding RTFSISOMAKERCMDOPTS::afNameSpecifiers
     
    357354    /** Specified path. */
    358355    char                szPath[RTPATH_MAX];
    359 } RTFSISOMAKERCMDPARSEDNAME;
     356} RTFSISOMKCMDPARSEDNAME;
    360357/** Pointer to a parsed name. */
    361 typedef RTFSISOMAKERCMDPARSEDNAME *PRTFSISOMAKERCMDPARSEDNAME;
     358typedef RTFSISOMKCMDPARSEDNAME *PRTFSISOMKCMDPARSEDNAME;
    362359/** Pointer to a const parsed name. */
    363 typedef RTFSISOMAKERCMDPARSEDNAME const *PCRTFSISOMAKERCMDPARSEDNAME;
     360typedef RTFSISOMKCMDPARSEDNAME const *PCRTFSISOMKCMDPARSEDNAME;
     361
     362
     363/**
     364 * Parsed names.
     365 */
     366typedef struct RTFSISOMKCMDPARSEDNAMES
     367{
     368    /** Number of names. */
     369    uint32_t                cNames;
     370    /** Number of names with the source. */
     371    uint32_t                cNamesWithSrc;
     372    /** Special source types.
     373     * Used for conveying commands to do on names intead of adding a source.
     374     * Only used when adding generic stuff w/o any options involved.  */
     375    enum
     376    {
     377        kSrcType_None,
     378        kSrcType_Normal,
     379        kSrcType_Remove,
     380        kSrcType_MustRemove
     381    }                       enmSrcType;
     382    /** The parsed names. */
     383    RTFSISOMKCMDPARSEDNAME  aNames[RTFSISOMAKERCMD_MAX_NAMES + 1];
     384} RTFSISOMKCMDPARSEDNAMES;
     385/** Pointer to parsed names. */
     386typedef RTFSISOMKCMDPARSEDNAMES *PRTFSISOMKCMDPARSEDNAMES;
     387/** Pointer to const parsed names. */
     388typedef RTFSISOMKCMDPARSEDNAMES *PCRTFSISOMKCMDPARSEDNAMES;
     389
    364390
    365391
     
    10371063
    10381064/**
    1039  * Adds a file.
     1065 * Processes a non-option argument.
    10401066 *
    10411067 * @returns IPRT status code.
    10421068 * @param   pOpts               The ISO maker command instance.
    1043  * @param   pszSrc              The path to the source file.
    1044  * @param   paParsedNames       Array of parsed names, there are
    1045  *                              pOpts->cNameSpecifiers entries in the array.
    1046  */
    1047 static int rtFsIsoMakerCmdAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMAKERCMDPARSEDNAME paParsedNames)
    1048 {
    1049     uint32_t idxObj;
    1050     int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj);
    1051     if (RT_SUCCESS(rc))
    1052     {
    1053         pOpts->cItemsAdded++;
    1054 
    1055         for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
    1056             if (paParsedNames[i].cchPath > 0)
    1057             {
    1058                 if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)
    1059                 {
    1060                     rc = RTFsIsoMakerObjSetPath(pOpts->hIsoMaker, idxObj,
    1061                                                 paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
    1062                                                 paParsedNames[i].szPath);
    1063                     if (RT_FAILURE(rc))
    1064                     {
    1065                         rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting name '%s' on '%s': %Rrc",
    1066                                                     paParsedNames[i].szPath, pszSrc, rc);
    1067                         break;
    1068                     }
    1069                 }
    1070                 if (paParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK)
    1071                 {
    1072                     /** @todo add APIs for this.   */
    1073                 }
    1074             }
    1075     }
    1076     else
    1077         rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc);
    1078     return rc;
    1079 }
    1080 
    1081 
    1082 /**
    1083  * Processes a non-option argument.
    1084  *
    1085  * @returns IPRT status code.
    1086  * @param   pOpts               The ISO maker command instance.
    10871069 * @param   pszSpec             The specification of what to add.
    1088  */
    1089 static int rtFsIsoMakerCmdAddSomething(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec)
    1090 {
    1091     const char * const pszSpecIn = pszSpec;
    1092     enum { kSpecialSrc_Normal, kSpecialSrc_Remove, kSpecialSrc_MustRemove } enmSpecialSrc = kSpecialSrc_Normal;
     1070 * @param   fWithSrc            Whether the specification includes a source path
     1071 *                              or not.
     1072 * @param   pParsed             Where to return the parsed name specification.
     1073 */
     1074static int rtFsIsoMakerCmdParseNameSpec(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec, bool fWithSrc,
     1075                                        PRTFSISOMKCMDPARSEDNAMES pParsed)
     1076{
     1077    const char * const  pszSpecIn = pszSpec;
     1078    uint32_t const      cMaxNames = pOpts->cNameSpecifiers + fWithSrc;
    10931079
    10941080    /*
    1095      * Split it up by '='.  Because of the source, which comes last,
     1081     * Split it up by '='.
    10961082     */
    1097     RTFSISOMAKERCMDPARSEDNAME   aParsedNames[RTFSISOMAKERCMD_MAX_NAMES + 1];
    1098     uint32_t                    cParsedNames = 0;
     1083    pParsed->cNames        = 0;
     1084    pParsed->cNamesWithSrc = 0;
     1085    pParsed->enmSrcType    = fWithSrc ? RTFSISOMKCMDPARSEDNAMES::kSrcType_Normal : RTFSISOMKCMDPARSEDNAMES::kSrcType_None;
    10991086    for (;;)
    11001087    {
    11011088        const char *pszEqual   = strchr(pszSpec, '=');
    11021089        size_t      cchName    = pszEqual ? pszEqual - pszSpec : strlen(pszSpec);
    1103         bool        fNeedSlash = pszEqual && !RTPATH_IS_SLASH(*pszSpec) && cchName > 0;
    1104         if (cchName + fNeedSlash >= sizeof(aParsedNames[cParsedNames].szPath))
    1105             return rtFsIsoMakerCmdSyntaxError(pOpts, "name #%u (0-based) is too long: %s", cParsedNames, pszSpecIn);
    1106         if (cParsedNames >= pOpts->cNameSpecifiers + 1)
    1107             return rtFsIsoMakerCmdSyntaxError(pOpts, "too many names specified (max %u + source): %s",
    1108                                               pOpts->cNameSpecifiers, pszSpecIn);
     1090        bool        fNeedSlash = (pszEqual || !fWithSrc) && !RTPATH_IS_SLASH(*pszSpec) && cchName > 0;
     1091        if (cchName + fNeedSlash >= sizeof(pParsed->aNames[pParsed->cNamesWithSrc].szPath))
     1092            return rtFsIsoMakerCmdSyntaxError(pOpts, "name #%u (0-based) is too long: %s", pParsed->cNamesWithSrc, pszSpecIn);
     1093        if (pParsed->cNamesWithSrc >= cMaxNames)
     1094            return rtFsIsoMakerCmdSyntaxError(pOpts, "too many names specified (max %u%s): %s",
     1095                                              pOpts->cNameSpecifiers, fWithSrc ? " + source" : "", pszSpecIn);
    11091096        if (!fNeedSlash)
    1110             memcpy(aParsedNames[cParsedNames].szPath, pszSpec, cchName);
     1097            memcpy(pParsed->aNames[pParsed->cNamesWithSrc].szPath, pszSpec, cchName);
    11111098        else
    11121099        {
    1113             memcpy(&aParsedNames[cParsedNames].szPath[1], pszSpec, cchName);
    1114             aParsedNames[cParsedNames].szPath[0] = RTPATH_SLASH;
     1100            memcpy(&pParsed->aNames[pParsed->cNamesWithSrc].szPath[1], pszSpec, cchName);
     1101            pParsed->aNames[pParsed->cNamesWithSrc].szPath[0] = RTPATH_SLASH;
    11151102            cchName++;
    11161103        }
    1117         aParsedNames[cParsedNames].szPath[cchName] = '\0';
    1118         aParsedNames[cParsedNames].cchPath = (uint32_t)cchName;
    1119         cParsedNames++;
    1120 
    1121         if (!pszEqual)
     1104        pParsed->aNames[pParsed->cNamesWithSrc].szPath[cchName] = '\0';
     1105        pParsed->aNames[pParsed->cNamesWithSrc].cchPath = (uint32_t)cchName;
     1106        pParsed->cNamesWithSrc++;
     1107
     1108        if (!pszEqual && fWithSrc)
    11221109        {
    11231110            if (!cchName)
    11241111                return rtFsIsoMakerCmdSyntaxError(pOpts, "empty source file name: %s", pszSpecIn);
    11251112            if (cchName == 8 && strcmp(pszSpec, ":remove:") == 0)
    1126                 enmSpecialSrc = kSpecialSrc_Remove;
     1113                pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove;
    11271114            else if (cchName == 13 && strcmp(pszSpec, ":must-remove:") == 0)
    1128                 enmSpecialSrc = kSpecialSrc_MustRemove;
     1115                pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove;
    11291116            break;
    11301117        }
     
    11331120
    11341121    /*
    1135      * If there are too few names specified, move the source and repeat the penultimate name.
     1122     * If there are too few names specified, move the source and repeat the
     1123     * last non-source name.  If only source, convert source into a name spec.
    11361124     */
    1137     if (cParsedNames < pOpts->cNameSpecifiers + 1)
    1138     {
    1139         aParsedNames[pOpts->cNameSpecifiers] = aParsedNames[cParsedNames - 1];
    1140         uint32_t iSrc = cParsedNames >= 2 ? cParsedNames - 2 : 0;
     1125    if (pParsed->cNamesWithSrc < cMaxNames)
     1126    {
     1127        uint32_t iSrc;
     1128        if (!fWithSrc)
     1129            iSrc = pParsed->cNamesWithSrc - 1;
     1130        else
     1131        {
     1132            pParsed->aNames[pOpts->cNameSpecifiers] = pParsed->aNames[pParsed->cNamesWithSrc - 1];
     1133            iSrc = pParsed->cNamesWithSrc >= 2 ? pParsed->cNamesWithSrc - 2 : 0;
     1134        }
    11411135
    11421136        /* If the source is a input file name specifier, reduce it to something that starts with a slash. */
    1143         if (cParsedNames == 1)
     1137        if (pParsed->cNamesWithSrc == 1 && fWithSrc)
    11441138        {
    1145             if (RTVfsChainIsSpec(aParsedNames[iSrc].szPath))
     1139            if (RTVfsChainIsSpec(pParsed->aNames[iSrc].szPath))
    11461140            {
    11471141                uint32_t offError;
    11481142                char *pszFinalPath;
    1149                 int rc = RTVfsChainQueryFinalPath(aParsedNames[iSrc].szPath, &pszFinalPath, &offError);
     1143                int rc = RTVfsChainQueryFinalPath(pParsed->aNames[iSrc].szPath, &pszFinalPath, &offError);
    11501144                if (RT_FAILURE(rc))
    11511145                    return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryFinalPath",
    1152                                                      aParsedNames[iSrc].szPath, rc, offError, NULL);
    1153                 aParsedNames[iSrc].cchPath = (uint32_t)strlen(pszFinalPath);
     1146                                                     pParsed->aNames[iSrc].szPath, rc, offError, NULL);
     1147                pParsed->aNames[iSrc].cchPath = (uint32_t)strlen(pszFinalPath);
    11541148                if (RTPATH_IS_SLASH(*pszFinalPath))
    1155                     memcpy(aParsedNames[iSrc].szPath, pszFinalPath, aParsedNames[iSrc].cchPath + 1);
     1149                    memcpy(pParsed->aNames[iSrc].szPath, pszFinalPath, pParsed->aNames[iSrc].cchPath + 1);
    11561150                else
    11571151                {
    1158                     memcpy(&aParsedNames[iSrc].szPath[1], pszFinalPath, aParsedNames[iSrc].cchPath + 1);
    1159                     aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;
    1160                     aParsedNames[iSrc].cchPath++;
     1152                    memcpy(&pParsed->aNames[iSrc].szPath[1], pszFinalPath, pParsed->aNames[iSrc].cchPath + 1);
     1153                    pParsed->aNames[iSrc].szPath[0] = RTPATH_SLASH;
     1154                    pParsed->aNames[iSrc].cchPath++;
    11611155                }
    11621156                RTStrFree(pszFinalPath);
    11631157            }
    11641158#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
    1165             else if (   RTPATH_IS_VOLSEP(aParsedNames[iSrc].szPath[1])
    1166                      && RT_C_IS_ALPHA(aParsedNames[iSrc].szPath[0]))
     1159            else if (   RTPATH_IS_VOLSEP(pParsed->aNames[iSrc].szPath[1])
     1160                     && RT_C_IS_ALPHA(pParsed->aNames[iSrc].szPath[0]))
    11671161            {
    1168                 if (RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[2]))
     1162                if (RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[2]))
    11691163                {
    1170                     memmove(&aParsedNames[iSrc].szPath[0], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1);
    1171                     aParsedNames[iSrc].cchPath -= 2;
     1164                    memmove(&pParsed->aNames[iSrc].szPath[0], &pParsed->aNames[iSrc].szPath[2], pParsed->aNames[iSrc].cchPath - 1);
     1165                    pParsed->aNames[iSrc].cchPath -= 2;
    11721166                }
    11731167                else
    11741168                {
    1175                     memmove(&aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[2], aParsedNames[iSrc].cchPath - 1);
    1176                     aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;
    1177                     aParsedNames[iSrc].cchPath  -= 1;
     1169                    memmove(&pParsed->aNames[iSrc].szPath[1], &pParsed->aNames[iSrc].szPath[2], pParsed->aNames[iSrc].cchPath - 1);
     1170                    pParsed->aNames[iSrc].szPath[0] = RTPATH_SLASH;
     1171                    pParsed->aNames[iSrc].cchPath  -= 1;
    11781172                }
    11791173            }
    11801174#endif
    1181             else if (!RTPATH_IS_SLASH(aParsedNames[iSrc].szPath[0]))
     1175            else if (!RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[0]))
    11821176            {
    1183                 if (aParsedNames[iSrc].cchPath + 2 > sizeof(aParsedNames[iSrc].szPath))
     1177                if (pParsed->aNames[iSrc].cchPath + 2 > sizeof(pParsed->aNames[iSrc].szPath))
    11841178                    return rtFsIsoMakerCmdSyntaxError(pOpts, "name too long: %s", pszSpecIn);
    1185                 memmove(&aParsedNames[iSrc].szPath[1], &aParsedNames[iSrc].szPath[0], aParsedNames[iSrc].cchPath + 1);
    1186                 aParsedNames[iSrc].szPath[0] = RTPATH_SLASH;
    1187                 aParsedNames[iSrc].cchPath++;
     1179                memmove(&pParsed->aNames[iSrc].szPath[1], &pParsed->aNames[iSrc].szPath[0], pParsed->aNames[iSrc].cchPath + 1);
     1180                pParsed->aNames[iSrc].szPath[0] = RTPATH_SLASH;
     1181                pParsed->aNames[iSrc].cchPath++;
    11881182            }
    11891183        }
    11901184
    11911185        for (uint32_t iDst = iSrc + 1; iDst < pOpts->cNameSpecifiers; iDst++)
    1192             aParsedNames[iDst] = aParsedNames[iSrc];
    1193         cParsedNames = pOpts->cNameSpecifiers + 1;
    1194     }
     1186            pParsed->aNames[iDst] = pParsed->aNames[iSrc];
     1187
     1188        pParsed->cNamesWithSrc = cMaxNames;
     1189    }
     1190    pParsed->cNames = pOpts->cNameSpecifiers;
    11951191
    11961192    /*
     
    11991195    for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
    12001196    {
    1201         aParsedNames[i].fNameSpecifiers = pOpts->afNameSpecifiers[i];
    1202         Assert(   aParsedNames[i].cchPath == 0
    1203                || RTPATH_IS_SLASH(aParsedNames[i].szPath[0]));
    1204     }
     1197        pParsed->aNames[i].fNameSpecifiers = pOpts->afNameSpecifiers[i];
     1198        Assert(   pParsed->aNames[i].cchPath == 0
     1199               || RTPATH_IS_SLASH(pParsed->aNames[i].szPath[0]));
     1200    }
     1201
     1202    return VINF_SUCCESS;
     1203}
     1204
     1205
     1206/**
     1207 * Enteres an object into the namespace by full paths.
     1208 *
     1209 * This is used by rtFsIsoMakerCmdOptEltoritoSetBootCatalogPath and
     1210 * rtFsIsoMakerCmdAddFile.
     1211 *
     1212 * @returns IPRT status code.
     1213 * @param   pOpts           The ISO maker command instance.
     1214 * @param   idxObj          The configuration index of the object to be named.
     1215 * @param   pParsed         The parsed names.
     1216 * @param   pszSrcOrName    Source file or name.
     1217 */
     1218static int rtFsIsoMakerCmdSetObjPaths(PRTFSISOMAKERCMDOPTS pOpts, uint32_t idxObj, PCRTFSISOMKCMDPARSEDNAMES pParsed,
     1219                                      const char *pszSrcOrName)
     1220{
     1221    int rc = VINF_SUCCESS;
     1222    for (uint32_t i = 0; i < pParsed->cNames; i++)
     1223        if (pParsed->aNames[i].cchPath > 0)
     1224        {
     1225            if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)
     1226            {
     1227                rc = RTFsIsoMakerObjSetPath(pOpts->hIsoMaker, idxObj,
     1228                                            pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
     1229                                            pParsed->aNames[i].szPath);
     1230                if (RT_FAILURE(rc))
     1231                {
     1232                    rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error setting name '%s' on '%s': %Rrc",
     1233                                                pParsed->aNames[i].szPath, pszSrcOrName, rc);
     1234                    break;
     1235                }
     1236            }
     1237            if (pParsed->aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MINOR_MASK)
     1238            {
     1239                /** @todo add APIs for this.   */
     1240            }
     1241        }
     1242    return rc;
     1243}
     1244
     1245
     1246/**
     1247 * Adds a file.
     1248 *
     1249 * @returns IPRT status code.
     1250 * @param   pOpts               The ISO maker command instance.
     1251 * @param   pszSrc              The path to the source file.
     1252 * @param   pParsed             The parsed names.
     1253 * @param   pidxObj             Where to return the configuration index for the
     1254 *                              added file.  Optional.
     1255 */
     1256static int rtFsIsoMakerCmdAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMKCMDPARSEDNAMES pParsed,
     1257                                  uint32_t *pidxObj)
     1258{
     1259    uint32_t idxObj;
     1260    int rc = RTFsIsoMakerAddUnnamedFileWithSrcPath(pOpts->hIsoMaker, pszSrc, &idxObj);
     1261    if (RT_SUCCESS(rc))
     1262    {
     1263        pOpts->cItemsAdded++;
     1264        if (pidxObj)
     1265            *pidxObj = idxObj;
     1266
     1267        rc = rtFsIsoMakerCmdSetObjPaths(pOpts, idxObj, pParsed, pszSrc);
     1268    }
     1269    else
     1270        rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "Error adding '%s': %Rrc", pszSrc, rc);
     1271    return rc;
     1272}
     1273
     1274
     1275/**
     1276 * Adds a file after first making sure it's a file.
     1277 *
     1278 * @returns IPRT status code
     1279 * @param   pOpts               The ISO maker command instance.
     1280 * @param   pszSrc              The path to the source file.
     1281 * @param   pParsed             The parsed names.
     1282 * @param   pidxObj             Where to return the configuration index for the
     1283 *                              added file.  Optional.
     1284 */
     1285static int rtFsIsoMakerCmdStatAndAddFile(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSrc, PCRTFSISOMKCMDPARSEDNAMES pParsed,
     1286                                         uint32_t *pidxObj)
     1287{
     1288    RTFSOBJINFO     ObjInfo;
     1289    uint32_t        offError;
     1290    RTERRINFOSTATIC ErrInfo;
     1291    int rc = RTVfsChainQueryInfo(pszSrc, &ObjInfo, RTFSOBJATTRADD_UNIX,
     1292                                 RTPATH_F_FOLLOW_LINK, &offError, RTErrInfoInitStatic(&ErrInfo));
     1293    if (RT_FAILURE(rc))
     1294        return rtFsIsoMakerCmdChainError(pOpts, "RTVfsChainQueryInfo", pszSrc, rc, offError, &ErrInfo.Core);
     1295
     1296    if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
     1297        return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, pParsed, pidxObj);
     1298    return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_A_FILE, "Not a file: %s", pszSrc);
     1299}
     1300
     1301
     1302/**
     1303 * Processes a non-option argument.
     1304 *
     1305 * @returns IPRT status code.
     1306 * @param   pOpts               The ISO maker command instance.
     1307 * @param   pszSpec             The specification of what to add.
     1308 */
     1309static int rtFsIsoMakerCmdAddSomething(PRTFSISOMAKERCMDOPTS pOpts, const char *pszSpec)
     1310{
     1311    /*
     1312     * Parse the name spec.
     1313     */
     1314    RTFSISOMKCMDPARSEDNAMES Parsed;
     1315    int rc = rtFsIsoMakerCmdParseNameSpec(pOpts, pszSpec, true /*fWithSrc*/, &Parsed);
     1316    if (RT_FAILURE(rc))
     1317        return rc;
    12051318
    12061319    /*
    12071320     * Deal with special source filenames used to remove/change stuff.
    12081321     */
    1209     if (   enmSpecialSrc == kSpecialSrc_Remove
    1210         || enmSpecialSrc == kSpecialSrc_MustRemove)
     1322    if (   Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove
     1323        || Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove)
    12111324    {
    12121325        const char *pszFirstNm = NULL;
    12131326        uint32_t    cRemoved   = 0;
    12141327        for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++)
    1215             if (   aParsedNames[i].cchPath > 0
    1216                 && (aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))
     1328            if (   Parsed.aNames[i].cchPath > 0
     1329                && (Parsed.aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))
    12171330            {
    1218                 pszFirstNm = aParsedNames[i].szPath;
     1331                pszFirstNm = Parsed.aNames[i].szPath;
    12191332                uint32_t idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker,
    1220                                                                aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
    1221                                                                aParsedNames[i].szPath);
     1333                                                               Parsed.aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK,
     1334                                                               Parsed.aNames[i].szPath);
    12221335                if (idxObj != UINT32_MAX)
    12231336                {
    12241337                    int rc = RTFsIsoMakerObjRemove(pOpts->hIsoMaker, idxObj);
    12251338                    if (RT_FAILURE(rc))
    1226                         return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpecIn, rc);
     1339                        return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpec, rc);
    12271340                    cRemoved++;
    12281341                }
    12291342            }
    1230         if (   enmSpecialSrc == kSpecialSrc_MustRemove
     1343        if (   Parsed.enmSrcType  == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove
    12311344            && cRemoved == 0)
    1232             return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpecIn);
     1345            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpec);
    12331346    }
    12341347    /*
     
    12371350    else
    12381351    {
    1239         const char     *pszSrc = aParsedNames[cParsedNames - 1].szPath;
     1352        const char     *pszSrc = Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath;
    12401353        RTFSOBJINFO     ObjInfo;
    12411354        uint32_t        offError;
     
    12471360
    12481361        if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
    1249             return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, aParsedNames);
     1362            return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, &Parsed, NULL /*pidxObj*/);
     1363
    12501364        if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
    1251             return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpecIn);
     1365            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding directory '%s' failed: not implemented", pszSpec);
     1366
    12521367        if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
    1253             return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpecIn);
    1254         return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpecIn);
     1368            return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding symlink '%s' failed: not implemented", pszSpec);
     1369
     1370        return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_IMPLEMENTED, "Adding special file '%s' failed: not implemented", pszSpec);
    12551371    }
    12561372
     
    12951411
    12961412/**
    1297  * Deals with: --boot-catalog <path-spec>
    1298  *
    1299  * This enters the boot catalog into the namespaces of the image.  The path-spec
    1300  * is similar to what rtFsIsoMakerCmdAddSomething processes, only there isn't a
    1301  * source file part.
     1413 * Helper that makes sure we've got a validation boot entry.
    13021414 *
    13031415 * @returns IPRT status code
    13041416 * @param   pOpts               The ISO maker command instance.
    1305  * @param   pszGenericBootImage The generic boot image source.
    1306  */
    1307 static int rtFsIsoMakerCmdOptEltoritoSetBootCatalogPath(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootCat)
    1308 {
    1309     RT_NOREF(pOpts, pszBootCat);
    1310     return VERR_NOT_IMPLEMENTED;
    1311 }
    1312 
    1313 
    1314 /**
    1315  * Helper that makes sure we've got a validation boot entry.
    1316  *
    1317  * @returns IPRT status code
    1318  * @param   pOpts               The ISO maker command instance.
    1319  */
    1320 static void rtFsIsoMakerCmdOptEltoritoEnsureValiidationEntry(PRTFSISOMAKERCMDOPTS pOpts)
     1417 */
     1418static void rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(PRTFSISOMAKERCMDOPTS pOpts)
    13211419{
    13221420    if (pOpts->cBootCatEntries == 0)
     
    13401438static int rtFsIsoMakerCmdOptEltoritoEnsureSectionEntry(PRTFSISOMAKERCMDOPTS pOpts, bool fForceNew, uint32_t *pidxBootCat)
    13411439{
    1342     rtFsIsoMakerCmdOptEltoritoEnsureValiidationEntry(pOpts);
     1440    rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts);
    13431441
    13441442    uint32_t i = pOpts->cBootCatEntries;
     
    13641462                                                                :          RTFSISOMKCMDELTORITOENTRY::kEntryType_Section;
    13651463        pOpts->aBootCatEntries[i].u.Section.pszImageNameInIso   = NULL;
    1366         pOpts->aBootCatEntries[i].u.Section.idImage             = UINT32_MAX;
     1464        pOpts->aBootCatEntries[i].u.Section.idxImageObj         = UINT32_MAX;
    13671465        pOpts->aBootCatEntries[i].u.Section.fInsertBootInfoTable = false;
    13681466        pOpts->aBootCatEntries[i].u.Section.fBootable           = true;
     
    13801478
    13811479/**
     1480 * Deals with: --boot-catalog <path-spec>
     1481 *
     1482 * This enters the boot catalog into the namespaces of the image.  The path-spec
     1483 * is similar to what rtFsIsoMakerCmdAddSomething processes, only there isn't a
     1484 * source file part.
     1485 *
     1486 * @returns IPRT status code
     1487 * @param   pOpts               The ISO maker command instance.
     1488 * @param   pszGenericBootImage The generic boot image source.
     1489 */
     1490static int rtFsIsoMakerCmdOptEltoritoSetBootCatalogPath(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootCat)
     1491{
     1492    /* Make sure we'll fail later if no other boot options are present. */
     1493    rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts);
     1494
     1495    /* Parse the name spec. */
     1496    RTFSISOMKCMDPARSEDNAMES Parsed;
     1497    int rc = rtFsIsoMakerCmdParseNameSpec(pOpts, pszBootCat, false /*fWithSrc*/, &Parsed);
     1498    if (RT_SUCCESS(rc))
     1499    {
     1500        /* Query/create the boot catalog and enter it into the name spaces. */
     1501        uint32_t idxBootCatObj;
     1502        rc = RTFsIsoMakerQueryObjIdxForBootCatalog(pOpts->hIsoMaker, &idxBootCatObj);
     1503        if (RT_SUCCESS(rc))
     1504            rc = rtFsIsoMakerCmdSetObjPaths(pOpts, idxBootCatObj, &Parsed, "boot catalog");
     1505        else
     1506            rc = rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTFsIsoMakerQueryBootCatalogPathObjIdx failed: %Rrc", rc);
     1507    }
     1508    return rc;
     1509}
     1510
     1511
     1512/**
    13821513 * Deals with: --eltorito-add-image {file-spec}
    13831514 *
     
    13941525static int rtFsIsoMakerCmdOptEltoritoAddImage(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootImageSpec)
    13951526{
    1396     RT_NOREF(pOpts, pszBootImageSpec);
    1397     return VERR_NOT_IMPLEMENTED;
     1527    /* Parse the name spec. */
     1528    RTFSISOMKCMDPARSEDNAMES Parsed;
     1529    int rc = rtFsIsoMakerCmdParseNameSpec(pOpts, pszBootImageSpec, true /*fWithSrc*/, &Parsed);
     1530    if (RT_SUCCESS(rc))
     1531    {
     1532        uint32_t idxBootCat;
     1533        rc = rtFsIsoMakerCmdOptEltoritoEnsureSectionEntry(pOpts, false /*fForceNew*/, &idxBootCat);
     1534        if (RT_SUCCESS(rc))
     1535        {
     1536            if (   pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj != UINT32_MAX
     1537                || pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso != NULL)
     1538                rc = rtFsIsoMakerCmdSyntaxError(pOpts, "boot image already given for current El Torito entry (%#u)", idxBootCat);
     1539            else
     1540            {
     1541                uint32_t idxImageObj;
     1542                rc = rtFsIsoMakerCmdStatAndAddFile(pOpts, Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath, &Parsed, &idxImageObj);
     1543                if (RT_SUCCESS(rc))
     1544                    pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj;
     1545            }
     1546        }
     1547    }
     1548
     1549    return rc;
    13981550}
    13991551
     
    14141566    if (RT_SUCCESS(rc))
    14151567    {
    1416         if (   pOpts->aBootCatEntries[idxBootCat].u.Section.idImage != UINT32_MAX
     1568        if (   pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj != UINT32_MAX
    14171569            || pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso != NULL)
    14181570            return rtFsIsoMakerCmdSyntaxError(pOpts, "boot image already given for current El Torito entry (%#u)", idxBootCat);
    14191571
    1420         uint32_t idxObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, RTFSISOMAKER_NAMESPACE_ALL, pszBootImage);
    1421         pOpts->aBootCatEntries[idxBootCat].u.Section.idImage = idxObj;
    1422         if (idxObj == UINT32_MAX)
     1572        uint32_t idxImageObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, RTFSISOMAKER_NAMESPACE_ALL, pszBootImage);
     1573        if (idxImageObj == UINT32_MAX)
    14231574            pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso = pszBootImage;
     1575        pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj;
    14241576    }
    14251577    return rc;
     
    14591611    if (pOpts->cBootCatEntries <= 1)
    14601612    {
    1461         rtFsIsoMakerCmdOptEltoritoEnsureValiidationEntry(pOpts);
     1613        rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts);
    14621614        pOpts->aBootCatEntries[0].u.Validation.idPlatform = idPlatform;
    14631615    }
     
    15751727        pOpts->aBootCatEntries[idxBootCat].u.Section.fInsertBootInfoTable = true;
    15761728    return rc;
     1729}
     1730
     1731
     1732/**
     1733 * Validates and commits the boot catalog stuff.
     1734 *
     1735 * ASSUMING this is called after all options are parsed and there is only this
     1736 * one call.
     1737 *
     1738 * @returns IPRT status code
     1739 * @param   pOpts               The ISO maker command instance.
     1740 */
     1741static int rtFsIsoMakerCmdOptEltoritoCommitBootCatalog(PRTFSISOMAKERCMDOPTS pOpts)
     1742{
     1743    if (pOpts->cBootCatEntries == 0)
     1744        return VINF_SUCCESS;
     1745
     1746    /*
     1747     * Locate and configure the boot images first.
     1748     */
     1749    for (uint32_t idxBootCat = 1; idxBootCat < pOpts->cBootCatEntries; idxBootCat++)
     1750        if (   pOpts->aBootCatEntries[idxBootCat].enmType == RTFSISOMKCMDELTORITOENTRY::kEntryType_Default
     1751            || pOpts->aBootCatEntries[idxBootCat].enmType == RTFSISOMKCMDELTORITOENTRY::kEntryType_Section)
     1752        {
     1753            /* Make sure we've got a boot image. */
     1754            uint32_t idxImageObj = pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj;
     1755            if (idxImageObj == UINT32_MAX)
     1756            {
     1757                const char *pszBootImage = pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso;
     1758                if (pszBootImage == NULL)
     1759                    return rtFsIsoMakerCmdSyntaxError(pOpts, "No image name given for boot catalog entry #%u", idxBootCat);
     1760
     1761                idxImageObj = RTFsIsoMakerGetObjIdxForPath(pOpts->hIsoMaker, RTFSISOMAKER_NAMESPACE_ALL, pszBootImage);
     1762                if (idxImageObj == UINT32_MAX)
     1763                    return rtFsIsoMakerCmdSyntaxError(pOpts, "Unable to locate image for boot catalog entry #%u: %s",
     1764                                                      idxBootCat, pszBootImage);
     1765                pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj;
     1766            }
     1767
     1768            /* Enable patching it? */
     1769            if (pOpts->aBootCatEntries[idxBootCat].u.Section.fInsertBootInfoTable)
     1770            {
     1771                int rc = RTFsIsoMakerObjEnableBootInfoTablePatching(pOpts->hIsoMaker, idxImageObj, true);
     1772                if (RT_FAILURE(rc))
     1773                    return rtFsIsoMakerCmdErrorRc(pOpts, rc,
     1774                                                  "RTFsIsoMakerObjEnableBootInfoTablePatching failed on entry #%u: %Rrc\n",
     1775                                                  idxBootCat, rc);
     1776            }
     1777
     1778            /* Figure out the floppy type given the object size. */
     1779            if (pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType == ISO9660_ELTORITO_BOOT_MEDIA_TYPE_MASK)
     1780            {
     1781                uint64_t cbImage;
     1782                int rc = RTFsIsoMakerObjQueryDataSize(pOpts->hIsoMaker, idxImageObj, &cbImage);
     1783                if (RT_FAILURE(rc))
     1784                    return rtFsIsoMakerCmdErrorRc(pOpts, rc, "RTFsIsoMakerObjGetDataSize failed on entry #%u: %Rrc\n",
     1785                                                  idxBootCat, rc);
     1786                if (cbImage == 1228800)
     1787                    pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_1_2_MB;
     1788                else if (cbImage <= 1474560)
     1789                    pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_1_44_MB;
     1790                else if (cbImage <= 2949120)
     1791                    pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_2_88_MB;
     1792                else
     1793                    pOpts->aBootCatEntries[idxBootCat].u.Section.bBootMediaType = ISO9660_ELTORITO_BOOT_MEDIA_TYPE_HARD_DISK;
     1794            }
     1795        }
     1796
     1797    /*
     1798     * Add the boot catalog entries.
     1799     */
     1800
     1801
     1802    return VINF_SUCCESS;
    15771803}
    15781804
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