Changeset 67437 in vbox for trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp
- Timestamp:
- Jun 16, 2017 1:14:39 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 116168
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/isomakercmd.cpp
r67434 r67437 268 268 * pszImageNameInIso is used (i.e. -b option) and we've delayed everything 269 269 * boot related till after all files have been added to the image. */ 270 uint32_t id Image;270 uint32_t idxImageObj; 271 271 /** Whether to insert boot info table into the image. */ 272 272 bool fInsertBootInfoTable; 273 273 /** Bootble or not. Possible to make BIOS set up emulation w/o booting it. */ 274 274 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). */ 277 276 uint8_t bBootMediaType; 278 277 /** File system / partition type. */ … … 332 331 /** Number of boot catalog entries (aBootCatEntries). */ 333 332 uint32_t cBootCatEntries; 334 /** Number of boot catalog entries we're done with (i.e. added to hIsoMaker). */335 uint32_t cBootCatEntriesDone;336 333 /** Boot catalog entries. */ 337 334 RTFSISOMKCMDELTORITOENTRY aBootCatEntries[64]; … … 346 343 347 344 /** 348 * Parsed name.349 */ 350 typedef struct RTFSISOM AKERCMDPARSEDNAME345 * One parsed name. 346 */ 347 typedef struct RTFSISOMKCMDPARSEDNAME 351 348 { 352 349 /** Copy of the corresponding RTFSISOMAKERCMDOPTS::afNameSpecifiers … … 357 354 /** Specified path. */ 358 355 char szPath[RTPATH_MAX]; 359 } RTFSISOM AKERCMDPARSEDNAME;356 } RTFSISOMKCMDPARSEDNAME; 360 357 /** Pointer to a parsed name. */ 361 typedef RTFSISOM AKERCMDPARSEDNAME *PRTFSISOMAKERCMDPARSEDNAME;358 typedef RTFSISOMKCMDPARSEDNAME *PRTFSISOMKCMDPARSEDNAME; 362 359 /** Pointer to a const parsed name. */ 363 typedef RTFSISOMAKERCMDPARSEDNAME const *PCRTFSISOMAKERCMDPARSEDNAME; 360 typedef RTFSISOMKCMDPARSEDNAME const *PCRTFSISOMKCMDPARSEDNAME; 361 362 363 /** 364 * Parsed names. 365 */ 366 typedef 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. */ 386 typedef RTFSISOMKCMDPARSEDNAMES *PRTFSISOMKCMDPARSEDNAMES; 387 /** Pointer to const parsed names. */ 388 typedef RTFSISOMKCMDPARSEDNAMES *PCRTFSISOMKCMDPARSEDNAMES; 389 364 390 365 391 … … 1037 1063 1038 1064 /** 1039 * Adds a file.1065 * Processes a non-option argument. 1040 1066 * 1041 1067 * @returns IPRT status code. 1042 1068 * @param pOpts The ISO maker command instance. 1043 * @param pszSrc The path to the source file.1044 * @param paParsedNames Array of parsed names, there are1045 * 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 else1077 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.1087 1069 * @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 */ 1074 static 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; 1093 1079 1094 1080 /* 1095 * Split it up by '='. Because of the source, which comes last,1081 * Split it up by '='. 1096 1082 */ 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; 1099 1086 for (;;) 1100 1087 { 1101 1088 const char *pszEqual = strchr(pszSpec, '='); 1102 1089 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); 1109 1096 if (!fNeedSlash) 1110 memcpy( aParsedNames[cParsedNames].szPath, pszSpec, cchName);1097 memcpy(pParsed->aNames[pParsed->cNamesWithSrc].szPath, pszSpec, cchName); 1111 1098 else 1112 1099 { 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; 1115 1102 cchName++; 1116 1103 } 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) 1122 1109 { 1123 1110 if (!cchName) 1124 1111 return rtFsIsoMakerCmdSyntaxError(pOpts, "empty source file name: %s", pszSpecIn); 1125 1112 if (cchName == 8 && strcmp(pszSpec, ":remove:") == 0) 1126 enmSpecialSrc = kSpecialSrc_Remove;1113 pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove; 1127 1114 else if (cchName == 13 && strcmp(pszSpec, ":must-remove:") == 0) 1128 enmSpecialSrc = kSpecialSrc_MustRemove;1115 pParsed->enmSrcType = RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove; 1129 1116 break; 1130 1117 } … … 1133 1120 1134 1121 /* 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. 1136 1124 */ 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 } 1141 1135 1142 1136 /* 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) 1144 1138 { 1145 if (RTVfsChainIsSpec( aParsedNames[iSrc].szPath))1139 if (RTVfsChainIsSpec(pParsed->aNames[iSrc].szPath)) 1146 1140 { 1147 1141 uint32_t offError; 1148 1142 char *pszFinalPath; 1149 int rc = RTVfsChainQueryFinalPath( aParsedNames[iSrc].szPath, &pszFinalPath, &offError);1143 int rc = RTVfsChainQueryFinalPath(pParsed->aNames[iSrc].szPath, &pszFinalPath, &offError); 1150 1144 if (RT_FAILURE(rc)) 1151 1145 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); 1154 1148 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); 1156 1150 else 1157 1151 { 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++; 1161 1155 } 1162 1156 RTStrFree(pszFinalPath); 1163 1157 } 1164 1158 #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])) 1167 1161 { 1168 if (RTPATH_IS_SLASH( aParsedNames[iSrc].szPath[2]))1162 if (RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[2])) 1169 1163 { 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; 1172 1166 } 1173 1167 else 1174 1168 { 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; 1178 1172 } 1179 1173 } 1180 1174 #endif 1181 else if (!RTPATH_IS_SLASH( aParsedNames[iSrc].szPath[0]))1175 else if (!RTPATH_IS_SLASH(pParsed->aNames[iSrc].szPath[0])) 1182 1176 { 1183 if ( aParsedNames[iSrc].cchPath + 2 > sizeof(aParsedNames[iSrc].szPath))1177 if (pParsed->aNames[iSrc].cchPath + 2 > sizeof(pParsed->aNames[iSrc].szPath)) 1184 1178 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++; 1188 1182 } 1189 1183 } 1190 1184 1191 1185 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; 1195 1191 1196 1192 /* … … 1199 1195 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 1200 1196 { 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 */ 1218 static 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 */ 1256 static 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 */ 1285 static 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 */ 1309 static 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; 1205 1318 1206 1319 /* 1207 1320 * Deal with special source filenames used to remove/change stuff. 1208 1321 */ 1209 if ( enmSpecialSrc == kSpecialSrc_Remove1210 || enmSpecialSrc == kSpecialSrc_MustRemove)1322 if ( Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_Remove 1323 || Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove) 1211 1324 { 1212 1325 const char *pszFirstNm = NULL; 1213 1326 uint32_t cRemoved = 0; 1214 1327 for (uint32_t i = 0; i < pOpts->cNameSpecifiers; i++) 1215 if ( aParsedNames[i].cchPath > 01216 && ( aParsedNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK))1328 if ( Parsed.aNames[i].cchPath > 0 1329 && (Parsed.aNames[i].fNameSpecifiers & RTFSISOMAKERCMDNAME_MAJOR_MASK)) 1217 1330 { 1218 pszFirstNm = aParsedNames[i].szPath;1331 pszFirstNm = Parsed.aNames[i].szPath; 1219 1332 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); 1222 1335 if (idxObj != UINT32_MAX) 1223 1336 { 1224 1337 int rc = RTFsIsoMakerObjRemove(pOpts->hIsoMaker, idxObj); 1225 1338 if (RT_FAILURE(rc)) 1226 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpec In, rc);1339 return rtFsIsoMakerCmdErrorRc(pOpts, rc, "Failed to remove '%s': %Rrc", pszSpec, rc); 1227 1340 cRemoved++; 1228 1341 } 1229 1342 } 1230 if ( enmSpecialSrc == kSpecialSrc_MustRemove1343 if ( Parsed.enmSrcType == RTFSISOMKCMDPARSEDNAMES::kSrcType_MustRemove 1231 1344 && cRemoved == 0) 1232 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpec In);1345 return rtFsIsoMakerCmdErrorRc(pOpts, VERR_NOT_FOUND, "Failed to locate '%s' for removal", pszSpec); 1233 1346 } 1234 1347 /* … … 1237 1350 else 1238 1351 { 1239 const char *pszSrc = aParsedNames[cParsedNames- 1].szPath;1352 const char *pszSrc = Parsed.aNames[Parsed.cNamesWithSrc - 1].szPath; 1240 1353 RTFSOBJINFO ObjInfo; 1241 1354 uint32_t offError; … … 1247 1360 1248 1361 if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) 1249 return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, aParsedNames); 1362 return rtFsIsoMakerCmdAddFile(pOpts, pszSrc, &Parsed, NULL /*pidxObj*/); 1363 1250 1364 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 1252 1367 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); 1255 1371 } 1256 1372 … … 1295 1411 1296 1412 /** 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. 1302 1414 * 1303 1415 * @returns IPRT status code 1304 1416 * @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 */ 1418 static void rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(PRTFSISOMAKERCMDOPTS pOpts) 1321 1419 { 1322 1420 if (pOpts->cBootCatEntries == 0) … … 1340 1438 static int rtFsIsoMakerCmdOptEltoritoEnsureSectionEntry(PRTFSISOMAKERCMDOPTS pOpts, bool fForceNew, uint32_t *pidxBootCat) 1341 1439 { 1342 rtFsIsoMakerCmdOptEltoritoEnsureVali idationEntry(pOpts);1440 rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts); 1343 1441 1344 1442 uint32_t i = pOpts->cBootCatEntries; … … 1364 1462 : RTFSISOMKCMDELTORITOENTRY::kEntryType_Section; 1365 1463 pOpts->aBootCatEntries[i].u.Section.pszImageNameInIso = NULL; 1366 pOpts->aBootCatEntries[i].u.Section.id Image= UINT32_MAX;1464 pOpts->aBootCatEntries[i].u.Section.idxImageObj = UINT32_MAX; 1367 1465 pOpts->aBootCatEntries[i].u.Section.fInsertBootInfoTable = false; 1368 1466 pOpts->aBootCatEntries[i].u.Section.fBootable = true; … … 1380 1478 1381 1479 /** 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 */ 1490 static 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 /** 1382 1513 * Deals with: --eltorito-add-image {file-spec} 1383 1514 * … … 1394 1525 static int rtFsIsoMakerCmdOptEltoritoAddImage(PRTFSISOMAKERCMDOPTS pOpts, const char *pszBootImageSpec) 1395 1526 { 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; 1398 1550 } 1399 1551 … … 1414 1566 if (RT_SUCCESS(rc)) 1415 1567 { 1416 if ( pOpts->aBootCatEntries[idxBootCat].u.Section.id Image!= UINT32_MAX1568 if ( pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj != UINT32_MAX 1417 1569 || pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso != NULL) 1418 1570 return rtFsIsoMakerCmdSyntaxError(pOpts, "boot image already given for current El Torito entry (%#u)", idxBootCat); 1419 1571 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) 1423 1574 pOpts->aBootCatEntries[idxBootCat].u.Section.pszImageNameInIso = pszBootImage; 1575 pOpts->aBootCatEntries[idxBootCat].u.Section.idxImageObj = idxImageObj; 1424 1576 } 1425 1577 return rc; … … 1459 1611 if (pOpts->cBootCatEntries <= 1) 1460 1612 { 1461 rtFsIsoMakerCmdOptEltoritoEnsureVali idationEntry(pOpts);1613 rtFsIsoMakerCmdOptEltoritoEnsureValidationEntry(pOpts); 1462 1614 pOpts->aBootCatEntries[0].u.Validation.idPlatform = idPlatform; 1463 1615 } … … 1575 1727 pOpts->aBootCatEntries[idxBootCat].u.Section.fInsertBootInfoTable = true; 1576 1728 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 */ 1741 static 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; 1577 1803 } 1578 1804
Note:
See TracChangeset
for help on using the changeset viewer.