- Timestamp:
- Dec 27, 2021 4:55:00 AM (3 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/UnattendedInstaller.h
r92768 r93085 219 219 220 220 /** 221 * Creates and formats (FAT12) a floppy image, then opens a VFS for it. 221 * Creates and formats (FAT12) a floppy image. 222 * 223 * This can be overridden to do more preparation work or/and create a different 224 * sized floppy. 222 225 * 223 226 * @returns COM status code. 224 227 * @param pszFilename The path to the image file. 225 228 * @param fOverwrite Whether to overwrite the file. 226 * @param phVfs Where to return a writable VFShandle to the newly229 * @param phVfsFile Where to return a read-writable handle to the newly 227 230 * created image. 228 231 */ 229 HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFS phVfs);232 virtual HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile); 230 233 231 234 /** … … 250 253 */ 251 254 HRESULT addScriptToFloppyImage(BaseTextScript *pEditor, RTVFS hVfs); 255 256 /** 257 * Copy an arbritrary file onto the floopy image. 258 * 259 * @returns COM status code. 260 * @param hVfs The VFS to add it to. 261 * @param pszSrc The source filename. 262 * @param pszDst The destination filename (on @a hVfs). 263 */ 264 HRESULT addFileToFloppyImage(RTVFS hVfs, const char *pszSrc, const char *pszDst); 252 265 253 266 /** … … 421 434 bool bootFromAuxiliaryIso() const { return false; } 422 435 }; 436 437 438 /** 439 * OS/2 installer. 440 */ 441 class UnattendedOs2Installer : public UnattendedInstaller 442 { 443 public: 444 DECLARE_TRANSLATE_METHODS(UnattendedOs2Installer) 445 446 UnattendedOs2Installer(Unattended *pParent, Utf8Str const &rStrHints); 447 ~UnattendedOs2Installer() {} 448 449 /* Remaster original ISO with auxiliary floppy used for el torito floppy emulation: */ 450 bool isOriginalIsoNeeded() const RT_OVERRIDE { return false; } 451 bool isAuxiliaryFloppyNeeded() const RT_OVERRIDE { return true; } 452 bool isAuxiliaryIsoNeeded() const RT_OVERRIDE { return true; } 453 454 protected: 455 HRESULT replaceAuxFloppyImageBootSector(RTVFSFILE hVfsFile) RT_NOEXCEPT; 456 HRESULT newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile) RT_OVERRIDE; 457 HRESULT copyFilesToAuxFloppyImage(RTVFS hVfs) RT_OVERRIDE; 458 HRESULT addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, 459 RTVFS hVfsOrgIso, bool fOverwrite) RT_OVERRIDE; 460 461 HRESULT splitResponseFile() RT_NOEXCEPT; 462 463 /** 464 * Splits up the given file into sub-files and writes them out with the auxilary 465 * path base as prefix. 466 * 467 * The source file contains @@VBOX_SPLITTER_START[filename]@@ and 468 * @@VBOX_SPLITTER_END[filename]@@ markup that is used to split it up. Any 469 * text between END and START tags are ignored and can be used for comments. 470 * 471 * @returns COM status code (error info set). 472 * @param pszFileToSplit The name of the file to split. 473 * @param rVecSplitFiles Vector where names of the sub-files are appended 474 * (without any path or prefix). 475 */ 476 HRESULT splitFile(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT; 477 478 /** 479 * Splits up the given editor output into sub-files and writes them out with the 480 * auxilary path base as prefix. 481 * 482 * The source file contains @@VBOX_SPLITTER_START[filename]@@ and 483 * @@VBOX_SPLITTER_END[filename]@@ markup that is used to split it up. Any 484 * text between END and START tags are ignored and can be used for comments. 485 * 486 * @returns COM status code (error info set). 487 * @param pEditor The editor which output should be split. 488 * @param rVecSplitFiles Vector where names of the sub-files are appended 489 * (without any path or prefix). 490 */ 491 HRESULT splitFile(BaseTextScript *pEditor, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT; 492 493 HRESULT splitFileInner(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles, 494 const char *pszSrc, size_t cbLeft) RT_NOEXCEPT; 495 496 /** The OS2SE20.SRC path (\OS2IMAGES). */ 497 Utf8Str mStrOs2Images; 498 /** Files split out from os2_response_files.rsp (bare filenames, no paths). */ 499 RTCList<RTCString> mVecSplitFiles; 500 }; 501 423 502 424 503 -
trunk/src/VBox/Main/src-server/UnattendedInstaller.cpp
r93082 r93085 44 44 #endif 45 45 #include <iprt/formats/iso9660.h> 46 #include <iprt/formats/fat.h> 46 47 #include <iprt/cpp/path.h> 47 48 … … 67 68 } 68 69 else if (enmOsType >= VBOXOSTYPE_OS2 && enmOsType < VBOXOSTYPE_Linux) 69 { 70 /** @todo OS/2 */ 71 } 70 pUinstaller = new UnattendedOs2Installer(pParent, strDetectedOSHints); 72 71 else 73 72 { … … 317 316 318 317 /* 319 * Create the image and get a VFS to it.320 */ 321 RTVFS hVfs;322 HRESULT hrc = newAuxFloppyImage(getAuxiliaryFloppyFilePath().c_str(), fOverwrite, &hVfs );318 * Create the image. 319 */ 320 RTVFSFILE hVfsFile; 321 HRESULT hrc = newAuxFloppyImage(getAuxiliaryFloppyFilePath().c_str(), fOverwrite, &hVfsFile); 323 322 if (SUCCEEDED(hrc)) 324 323 { 325 324 /* 326 * Call overridable method to copies the files onto it.325 * Open the FAT file system so we can copy files onto the floppy. 327 326 */ 328 hrc = copyFilesToAuxFloppyImage(hVfs); 329 330 /* 331 * Relase the VFS. On failure, delete the floppy image so the operation can 332 * be repeated in non-overwrite mode and we don't leave any mess behind. 333 */ 334 RTVfsRelease(hVfs); 335 327 RTERRINFOSTATIC ErrInfo; 328 RTVFS hVfs; 329 int vrc = RTFsFatVolOpen(hVfsFile, false /*fReadOnly*/, 0 /*offBootSector*/, &hVfs, RTErrInfoInitStatic(&ErrInfo)); 330 RTVfsFileRelease(hVfsFile); 331 if (RT_SUCCESS(vrc)) 332 { 333 /* 334 * Call overridable method to copies the files onto it. 335 */ 336 hrc = copyFilesToAuxFloppyImage(hVfs); 337 338 /* 339 * Release the VFS. On failure, delete the floppy image so the operation can 340 * be repeated in non-overwrite mode and so that we don't leave any mess behind. 341 */ 342 RTVfsRelease(hVfs); 343 } 344 else if (RTErrInfoIsSet(&ErrInfo.Core)) 345 hrc = mpParent->setErrorBoth(E_FAIL, vrc, 346 tr("Failed to open FAT file system on newly created floppy image '%s': %Rrc: %s"), 347 getAuxiliaryFloppyFilePath().c_str(), vrc, ErrInfo.Core.pszMsg); 348 else 349 hrc = mpParent->setErrorBoth(E_FAIL, vrc, 350 tr("Failed to open FAT file system onnewly created floppy image '%s': %Rrc"), 351 getAuxiliaryFloppyFilePath().c_str(), vrc); 336 352 if (FAILED(hrc)) 337 353 RTFileDelete(getAuxiliaryFloppyFilePath().c_str()); … … 340 356 } 341 357 342 HRESULT UnattendedInstaller::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFS phVfs)358 HRESULT UnattendedInstaller::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile) 343 359 { 344 360 /* … … 361 377 if (RT_SUCCESS(vrc)) 362 378 { 363 /* 364 * Open the FAT VFS. 365 */ 366 RTERRINFOSTATIC ErrInfo; 367 RTVFS hVfs; 368 vrc = RTFsFatVolOpen(hVfsFile, false /*fReadOnly*/, 0 /*offBootSector*/, &hVfs, RTErrInfoInitStatic(&ErrInfo)); 369 if (RT_SUCCESS(vrc)) 370 { 371 *phVfs = hVfs; 372 RTVfsFileRelease(hVfsFile); 373 LogRelFlow(("UnattendedInstaller::newAuxFloppyImage: created, formatted and opened '%s'\n", pszFilename)); 374 return S_OK; 375 } 376 377 if (RTErrInfoIsSet(&ErrInfo.Core)) 378 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to open newly created floppy image '%s': %Rrc: %s"), 379 pszFilename, vrc, ErrInfo.Core.pszMsg); 380 else 381 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to open newly created floppy image '%s': %Rrc"), 382 pszFilename, vrc); 383 } 384 else 385 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to format floppy image '%s': %Rrc"), pszFilename, vrc); 379 *phVfsFile = hVfsFile; 380 LogRelFlow(("UnattendedInstaller::newAuxFloppyImage: created and formatted '%s'\n", pszFilename)); 381 return S_OK; 382 } 383 384 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to format floppy image '%s': %Rrc"), pszFilename, vrc); 386 385 RTVfsFileRelease(hVfsFile); 387 386 RTFileDelete(pszFilename); … … 391 390 return hrc; 392 391 } 393 394 392 395 393 HRESULT UnattendedInstaller::copyFilesToAuxFloppyImage(RTVFS hVfs) … … 441 439 pEditor->getDefaultFilename(), getAuxiliaryFloppyFilePath().c_str()); 442 440 return hrc; 443 441 } 442 443 HRESULT UnattendedInstaller::addFileToFloppyImage(RTVFS hVfs, const char *pszSrc, const char *pszDst) 444 { 445 HRESULT hrc; 446 447 /* 448 * Open the source file. 449 */ 450 RTVFSIOSTREAM hVfsIosSrc; 451 int vrc = RTVfsIoStrmOpenNormal(pszSrc, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hVfsIosSrc); 452 if (RT_SUCCESS(vrc)) 453 { 454 /* 455 * Open the destination file. 456 */ 457 RTVFSFILE hVfsFileDst; 458 vrc = RTVfsFileOpen(hVfs, pszDst, 459 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_ALL | (0660 << RTFILE_O_CREATE_MODE_SHIFT), 460 &hVfsFileDst); 461 if (RT_SUCCESS(vrc)) 462 { 463 /* 464 * Do the copying. 465 */ 466 RTVFSIOSTREAM hVfsIosDst = RTVfsFileToIoStream(hVfsFileDst); 467 vrc = RTVfsUtilPumpIoStreams(hVfsIosSrc, hVfsIosDst, 0); 468 if (RT_SUCCESS(vrc)) 469 hrc = S_OK; 470 else 471 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error writing copying '%s' to floppy image '%s': %Rrc"), 472 pszSrc, getAuxiliaryFloppyFilePath().c_str(), vrc); 473 RTVfsIoStrmRelease(hVfsIosDst); 474 RTVfsFileRelease(hVfsFileDst); 475 } 476 else 477 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error opening '%s' on floppy image '%s' for writing: %Rrc"), 478 pszDst, getAuxiliaryFloppyFilePath().c_str(), vrc); 479 480 RTVfsIoStrmRelease(hVfsIosSrc); 481 } 482 else 483 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error opening '%s' for copying onto floppy image '%s': %Rrc"), 484 pszSrc, getAuxiliaryFloppyFilePath().c_str(), vrc); 485 return hrc; 444 486 } 445 487 … … 813 855 814 856 857 858 /********************************************************************************************************************************* 859 * Implementation of UnattendedOs2Installer * 860 *********************************************************************************************************************************/ 861 862 UnattendedOs2Installer::UnattendedOs2Installer(Unattended *pParent, Utf8Str const &rStrHints) 863 : UnattendedInstaller(pParent, 864 "os2_response_files.rsp", "os2_postinstall.cmd", 865 "OS2.RSP", "VBOXPOST.CMD", 866 DeviceType_Floppy) 867 { 868 Assert(!isOriginalIsoNeeded()); 869 Assert(isAuxiliaryFloppyNeeded()); 870 Assert(isAuxiliaryIsoIsVISO()); 871 Assert(bootFromAuxiliaryIso()); 872 mStrAuxiliaryInstallDir = "S:\\"; 873 874 /* Extract the info from the hints variable: */ 875 RTCList<RTCString, RTCString *> Pairs = rStrHints.split(" "); 876 size_t i = Pairs.size(); 877 Assert(i > 0); 878 while (i -- > 0) 879 { 880 RTCString const rStr = Pairs[i]; 881 if (rStr.startsWith("OS2SE20.SRC=")) 882 mStrOs2Images = rStr.substr(sizeof("OS2SE20.SRC=") - 1); 883 else 884 AssertMsgFailed(("Unknown hint: %s\n", rStr.c_str())); 885 } 886 } 887 888 889 HRESULT UnattendedOs2Installer::replaceAuxFloppyImageBootSector(RTVFSFILE hVfsFile) RT_NOEXCEPT 890 { 891 /* 892 * Find the bootsector. Because the ArcaOS ISOs doesn't contain any floppy 893 * images, we cannot just lift it off one of those. Instead we'll locate it 894 * in the SYSINSTX.COM utility, i.e. the tool which installs it onto floppies 895 * and harddisks. The SYSINSTX.COM utility is a NE executable and we don't 896 * have issues with compressed pages like with LX images. 897 * 898 * The utility seems always to be located on disk 0. 899 */ 900 RTVFS hVfsOrgIso; 901 HRESULT hrc = openInstallIsoImage(&hVfsOrgIso); 902 if (SUCCEEDED(hrc)) 903 { 904 char szPath[256]; 905 int vrc = RTPathJoin(szPath, sizeof(szPath), mStrOs2Images.c_str(), "DISK_0/SYSINSTX.COM"); 906 if (RT_SUCCESS(vrc)) 907 { 908 RTVFSFILE hVfsSysInstX; 909 vrc = RTVfsFileOpen(hVfsOrgIso, szPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, &hVfsSysInstX); 910 if (RT_SUCCESS(vrc)) 911 { 912 /* 913 * Scan the image looking for a 512 block ending with a DOS signature 914 * and starting with a three byte jump followed by an OEM name string. 915 */ 916 uint8_t *pbBootSector = NULL; 917 uint64_t off = 0; 918 bool fEof = false; 919 uint8_t abBuf[_8K] = {0}; 920 do 921 { 922 /* Read the next chunk. */ 923 memmove(abBuf, &abBuf[sizeof(abBuf) - 512], 512); /* Move up the last 512 (all zero the first time around). */ 924 size_t cbRead = 0; 925 vrc = RTVfsFileReadAt(hVfsSysInstX, off, &abBuf[512], sizeof(abBuf) - 512, &cbRead); 926 if (RT_FAILURE(vrc)) 927 break; 928 fEof = cbRead != sizeof(abBuf) - 512; 929 off += cbRead; 930 931 /* Scan it. */ 932 size_t cbLeft = sizeof(abBuf); 933 uint8_t *pbCur = abBuf; 934 while (cbLeft >= 512) 935 { 936 /* Look for the DOS signature (0x55 0xaa) at the end of the sector: */ 937 uint8_t *pbHit = (uint8_t *)memchr(pbCur + 510, 0x55, cbLeft - 510 - 1); 938 if (!pbHit) 939 break; 940 if (pbHit[1] == 0xaa) 941 { 942 uint8_t *pbStart = pbHit - 510; 943 if ( pbStart[0] == 0xeb /* JMP imm8 */ 944 && pbStart[1] >= 3 + 8 + sizeof(FATEBPB) - 2 /* must jump after the FATEBPB */ 945 && RT_C_IS_ALNUM(pbStart[3]) /* ASSUME OEM string starts with two letters (typically 'IBM x.y')*/ 946 && RT_C_IS_ALNUM(pbStart[4])) 947 { 948 FATEBPB *pBpb = (FATEBPB *)&pbStart[3 + 8]; 949 if ( pBpb->bExtSignature == FATEBPB_SIGNATURE 950 && ( memcmp(pBpb->achType, "FAT ", sizeof(pBpb->achType)) == 0 951 || memcmp(pBpb->achType, FATEBPB_TYPE_FAT12, sizeof(pBpb->achType)) == 0)) 952 { 953 pbBootSector = pbStart; 954 break; 955 } 956 } 957 } 958 959 /* skip */ 960 pbCur = pbHit - 510 + 1; 961 cbLeft = &abBuf[sizeof(abBuf)] - pbCur; 962 } 963 } while (!fEof); 964 965 if (pbBootSector) 966 { 967 if (pbBootSector != abBuf) 968 pbBootSector = (uint8_t *)memmove(abBuf, pbBootSector, 512); 969 970 /* 971 * We've now got a bootsector. So, we need to copy the EBPB 972 * from the destination image before replacing it. 973 */ 974 vrc = RTVfsFileReadAt(hVfsFile, 0, &abBuf[512], 512, NULL); 975 if (RT_SUCCESS(vrc)) 976 { 977 memcpy(&pbBootSector[3 + 8], &abBuf[512 + 3 + 8], sizeof(FATEBPB)); 978 979 /* 980 * Write it. 981 */ 982 vrc = RTVfsFileWriteAt(hVfsFile, 0, pbBootSector, 512, NULL); 983 if (RT_SUCCESS(vrc)) 984 { 985 LogFlowFunc(("Successfully installed new bootsector\n")); 986 hrc = S_OK; 987 } 988 else 989 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to write bootsector: %Rrc"), vrc); 990 } 991 else 992 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to read bootsector: %Rrc"), vrc); 993 } 994 else if (RT_FAILURE(vrc)) 995 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error reading SYSINSTX.COM: %Rrc"), vrc); 996 else 997 hrc = mpParent->setErrorBoth(E_FAIL, VERR_NOT_FOUND, 998 tr("Unable to locate bootsector template in SYSINSTX.COM")); 999 RTVfsFileRelease(hVfsSysInstX); 1000 } 1001 else 1002 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to open SYSINSTX.COM: %Rrc"), vrc); 1003 } 1004 else 1005 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to construct SYSINSTX.COM path")); 1006 RTVfsRelease(hVfsOrgIso); 1007 } 1008 return hrc; 1009 1010 } 1011 1012 HRESULT UnattendedOs2Installer::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFSFILE phVfsFile) 1013 { 1014 /* 1015 * Open the image file. 1016 */ 1017 HRESULT hrc; 1018 RTVFSFILE hVfsFile; 1019 uint64_t fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_ALL | (0660 << RTFILE_O_CREATE_MODE_SHIFT); 1020 if (fOverwrite) 1021 fOpen |= RTFILE_O_CREATE_REPLACE; 1022 else 1023 fOpen |= RTFILE_O_OPEN; 1024 int vrc = RTVfsFileOpenNormal(pszFilename, fOpen, &hVfsFile); 1025 if (RT_SUCCESS(vrc)) 1026 { 1027 /* 1028 * Format it. 1029 */ 1030 vrc = RTFsFatVolFormat288(hVfsFile, false /*fQuick*/); 1031 if (RT_SUCCESS(vrc)) 1032 { 1033 /* 1034 * Now we install the OS/2 boot sector on it. 1035 */ 1036 hrc = replaceAuxFloppyImageBootSector(hVfsFile); 1037 if (SUCCEEDED(hrc)) 1038 { 1039 *phVfsFile = hVfsFile; 1040 LogRelFlow(("UnattendedInstaller::newAuxFloppyImage: created and formatted '%s'\n", pszFilename)); 1041 return S_OK; 1042 } 1043 } 1044 else 1045 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to format floppy image '%s': %Rrc"), pszFilename, vrc); 1046 RTVfsFileRelease(hVfsFile); 1047 RTFileDelete(pszFilename); 1048 } 1049 else 1050 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to create floppy image '%s': %Rrc"), pszFilename, vrc); 1051 return hrc; 1052 } 1053 1054 1055 HRESULT UnattendedOs2Installer::splitResponseFile() RT_NOEXCEPT 1056 { 1057 if (mVecSplitFiles.size() == 0) 1058 { 1059 #if 0 1060 Utf8Str strResponseFile; 1061 int vrc = strResponseFile.assignNoThrow(mpParent->i_getAuxiliaryBasePath()); 1062 if (RT_SUCCESS(vrc)) 1063 vrc = strResponseFile.appendNoThrow(mMainScript.getDefaultFilename()); 1064 if (RT_SUCCESS(vrc)) 1065 return splitFile(strResponseFile.c_str(), mVecSplitFiles); 1066 return mpParent->setErrorVrc(vrc); 1067 #else 1068 return splitFile(&mMainScript, mVecSplitFiles); 1069 #endif 1070 } 1071 return S_OK; 1072 } 1073 1074 HRESULT UnattendedOs2Installer::copyFilesToAuxFloppyImage(RTVFS hVfs) 1075 { 1076 /* 1077 * Make sure we've split the files already. 1078 */ 1079 HRESULT hrc = splitResponseFile(); 1080 if (FAILED(hrc)) 1081 return hrc; 1082 1083 /* 1084 * We need to copy over the files needed to boot OS/2. 1085 */ 1086 static struct 1087 { 1088 bool fMandatory; 1089 const char *apszNames[2]; 1090 const char *apszDisks[3]; 1091 const char *pszMinVer; 1092 const char *pszMaxVer; 1093 } const s_aFiles[] = 1094 { 1095 { true, { "OS2BOOT", NULL }, { "DISK_0", NULL, NULL }, "2.1", NULL }, /* 2.0 did not have OS2BOOT */ 1096 { true, { "OS2LDR", NULL }, { "DISK_0", NULL, NULL }, NULL, NULL }, 1097 { true, { "OS2LDR.MSG", NULL }, { "DISK_0", NULL, NULL }, NULL, NULL }, 1098 { true, { "OS2KRNL", "OS2KRNLI" }, { "DISK_0", NULL, NULL }, NULL, NULL }, 1099 { true, { "OS2DUMP", NULL }, { "DISK_0", NULL, NULL }, NULL, NULL }, 1100 // 1101 { true, { "ANSICALL.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1102 { true, { "BKSCALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1103 { true, { "BMSCALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1104 { true, { "BVHINIT.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1105 { true, { "BVSCALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1106 { true, { "CDFS.IFS", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1107 { true, { "CLOCK01.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1108 { true, { "COUNT437.SYS", "COUNTRY.SYS" }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1109 { true, { "DOS.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1110 { true, { "DOSCALL1.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1111 { true, { "IBM1FLPY.ADD", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1112 { true, { "IBM1S506.ADD", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1113 { true, { "IBMIDECD.FLT", NULL }, { "DISK_1", "DISK_2", NULL }, "4.0", NULL }, /* not in 2.1 & Warp3 */ 1114 { true, { "IBMKBD.SYS", "KBD01.SYS"/*?*/}, { "DISK_1", "DISK_2", NULL }, NULL, NULL}, 1115 { true, { "ISAPNP.SNP", NULL }, { "DISK_1", "DISK_2", NULL }, "4.0", NULL }, /* not in 2.1 */ 1116 { true, { "KBDBASE.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, "3.0", NULL }, /* not in 2.1 */ 1117 { true, { "KBDCALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1118 { true, { "KEYBOARD.DCP", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1119 { true, { "MOUCALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1120 { true, { "MSG.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1121 { true, { "NAMPIPES.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1122 { true, { "NLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1123 { true, { "OS2CDROM.DMD", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1124 { true, { "OS2CHAR.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1125 { true, { "OS2DASD.DMD", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1126 { true, { "OS2LVM.DMD", NULL }, { "DISK_1", "DISK_2", NULL }, "4.5", NULL }, 1127 { true, { "OS2VER", NULL }, { "DISK_0", NULL, NULL }, NULL, NULL }, 1128 { true, { "PNP.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, "4.0", NULL }, 1129 { true, { "QUECALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1130 { true, { "RESOURCE.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, "3.0", NULL }, /* not in 2.1*/ 1131 { true, { "SCREEN01.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1132 { true, { "SESMGR.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1133 { true, { "TESTCFG.SYS", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1134 { true, { "VIO437.DCP", "VTBL850.DCP" }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1135 { true, { "VIOCALLS.DLL", NULL }, { "DISK_1", "DISK_2", NULL }, NULL, NULL }, 1136 }; 1137 1138 1139 RTVFS hVfsOrgIso; 1140 hrc = openInstallIsoImage(&hVfsOrgIso); 1141 if (SUCCEEDED(hrc)) 1142 { 1143 for (size_t i = 0; i < RT_ELEMENTS(s_aFiles); i++) 1144 { 1145 bool fCopied = false; 1146 for (size_t iDisk = 0; iDisk < RT_ELEMENTS(s_aFiles[i].apszDisks) && s_aFiles[i].apszDisks[iDisk] && !fCopied; iDisk++) 1147 { 1148 for (size_t iName = 0; iName < RT_ELEMENTS(s_aFiles[i].apszNames) && s_aFiles[i].apszNames[iName]; iName++) 1149 { 1150 char szPath[256]; 1151 int vrc = RTPathJoin(szPath, sizeof(szPath), mStrOs2Images.c_str(), s_aFiles[i].apszDisks[iDisk]); 1152 if (RT_SUCCESS(vrc)) 1153 vrc = RTPathAppend(szPath, sizeof(szPath), s_aFiles[i].apszNames[iName]); 1154 AssertRCBreakStmt(vrc, hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("RTPathJoin/Append failed for %s: %Rrc"), 1155 s_aFiles[i].apszNames[iName], vrc)); 1156 RTVFSFILE hVfsSrc; 1157 vrc = RTVfsFileOpen(hVfsOrgIso, szPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, &hVfsSrc); 1158 if (RT_SUCCESS(vrc)) 1159 { 1160 RTVFSFILE hVfsDst; 1161 vrc = RTVfsFileOpen(hVfs, s_aFiles[i].apszNames[0], 1162 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE 1163 | (0755 << RTFILE_O_CREATE_MODE_SHIFT), &hVfsDst); 1164 if (RT_SUCCESS(vrc)) 1165 { 1166 RTVFSIOSTREAM hVfsIosSrc = RTVfsFileToIoStream(hVfsSrc); 1167 RTVFSIOSTREAM hVfsIosDst = RTVfsFileToIoStream(hVfsDst); 1168 vrc = RTVfsUtilPumpIoStreams(hVfsIosSrc, hVfsIosDst, 0); 1169 RTVfsIoStrmRelease(hVfsIosDst); 1170 RTVfsFileRelease(hVfsDst); 1171 RTVfsIoStrmRelease(hVfsIosSrc); 1172 if (RT_FAILURE(vrc)) 1173 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to write %s to the floppy: %Rrc"), 1174 s_aFiles[i].apszNames, vrc); 1175 } 1176 else 1177 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to open %s on floppy: %Rrc"), 1178 s_aFiles[i].apszNames, vrc); 1179 1180 RTVfsFileRelease(hVfsSrc); 1181 fCopied = true; 1182 break; 1183 } 1184 } 1185 } 1186 if (FAILED(hrc)) 1187 break; 1188 if (!fCopied) 1189 { 1190 /** @todo do version filtering. */ 1191 hrc = mpParent->setErrorBoth(E_FAIL, VERR_FILE_NOT_FOUND, 1192 tr("Failed to locate '%s' needed for the install floppy"), s_aFiles[i].apszNames[0]); 1193 break; 1194 } 1195 } 1196 RTVfsRelease(hVfsOrgIso); 1197 } 1198 1199 /* 1200 * In addition, we need to add a CONFIG.SYS and the startup script. 1201 */ 1202 if (SUCCEEDED(hrc)) 1203 { 1204 Utf8Str strSrc; 1205 try 1206 { 1207 strSrc = mpParent->i_getAuxiliaryBasePath(); 1208 strSrc.append("CONFIG.SYS"); 1209 } 1210 catch (std::bad_alloc &) 1211 { 1212 return E_OUTOFMEMORY; 1213 } 1214 hrc = addFileToFloppyImage(hVfs, strSrc.c_str(), "CONFIG.SYS"); 1215 } 1216 1217 /* 1218 * We also want a ALTF2ON.$$$ file so we can see which drivers are loaded 1219 * and where it might get stuck. 1220 */ 1221 if (SUCCEEDED(hrc)) 1222 { 1223 RTVFSFILE hVfsFile; 1224 int vrc = RTVfsFileOpen(hVfs, "ALTF2ON.$$$", 1225 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE 1226 | (0755 << RTFILE_O_CREATE_MODE_SHIFT), &hVfsFile); 1227 if (RT_SUCCESS(vrc)) 1228 { 1229 /** @todo buggy fat vfs: cannot write empty files */ 1230 RTVfsFileWrite(hVfsFile, RT_STR_TUPLE("\r\n"), NULL); 1231 RTVfsFileRelease(hVfsFile); 1232 } 1233 else 1234 hrc = mpParent->setErrorBoth(E_FAIL, VERR_FILE_NOT_FOUND, tr("Failed to create 'ALTF2ON.$$$' on the install floppy")); 1235 } 1236 1237 return hrc; 1238 } 1239 1240 HRESULT UnattendedOs2Installer::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles, 1241 RTVFS hVfsOrgIso, bool fOverwrite) 1242 { 1243 /* 1244 * Make sure we've split the files already. 1245 */ 1246 HRESULT hrc = splitResponseFile(); 1247 if (FAILED(hrc)) 1248 return hrc; 1249 1250 /* 1251 * Add our stuff to the vectors. 1252 */ 1253 try 1254 { 1255 /* Remaster ISO. */ 1256 rVecArgs.append() = "--no-file-mode"; 1257 rVecArgs.append() = "--no-dir-mode"; 1258 1259 rVecArgs.append() = "--import-iso"; 1260 rVecArgs.append(mpParent->i_getIsoPath()); 1261 1262 rVecArgs.append() = "--file-mode=0444"; 1263 rVecArgs.append() = "--dir-mode=0555"; 1264 1265 /* Add the boot floppy to the ISO: */ 1266 rVecArgs.append() = "--eltorito-new-entry"; 1267 rVecArgs.append() = "--eltorito-add-image"; 1268 rVecArgs.append(mStrAuxiliaryFloppyFilePath); 1269 rVecArgs.append() = "--eltorito-floppy-288"; 1270 1271 1272 /* Add the response files and postinstall files to the ISO: */ 1273 Utf8Str const &rStrAuxPrefix = mpParent->i_getAuxiliaryBasePath(); 1274 size_t i = mVecSplitFiles.size(); 1275 while (i-- > 0) 1276 { 1277 RTCString const &rStrFile = mVecSplitFiles[i]; 1278 rVecArgs.append().assign("VBoxCID/").append(rStrFile).append('=').append(rStrAuxPrefix).append(rStrFile); 1279 } 1280 } 1281 catch (std::bad_alloc &) 1282 { 1283 return E_OUTOFMEMORY; 1284 } 1285 1286 /* 1287 * Call parent. 1288 */ 1289 return UnattendedInstaller::addFilesToAuxVisoVectors(rVecArgs, rVecFiles, hVfsOrgIso, fOverwrite); 1290 } 1291 1292 /** 1293 * Helper for splitFile. 1294 */ 1295 const char *splitFileLocateSubstring(const char *pszSrc, size_t cchSrc, const char *pszSubstring, size_t cchSubstring) 1296 { 1297 char const ch0 = *pszSubstring; 1298 while (cchSrc >= cchSubstring) 1299 { 1300 const char *pszHit0 = (const char *)memchr(pszSrc, ch0, cchSrc - cchSubstring + 1); 1301 if (pszHit0) 1302 { 1303 if (memcmp(pszHit0, pszSubstring, cchSubstring) == 0) 1304 return pszHit0; 1305 } 1306 else 1307 break; 1308 cchSrc -= pszHit0 - pszSrc + 1; 1309 pszSrc = pszHit0 + 1; 1310 } 1311 return NULL; 1312 } 1313 1314 /** 1315 * Worker for splitFile(). 1316 */ 1317 HRESULT UnattendedOs2Installer::splitFileInner(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles, 1318 const char *pszSrc, size_t cbLeft) RT_NOEXCEPT 1319 { 1320 static const char s_szPrefix[] = "@@VBOX_SPLITTER_"; 1321 const char * const pszStart = pszSrc; 1322 const char * const pszEnd = &pszSrc[cbLeft]; 1323 while (cbLeft > 0) 1324 { 1325 /* 1326 * Locate the next split start marker (everything before it is ignored). 1327 */ 1328 const char *pszMarker = splitFileLocateSubstring(pszSrc, cbLeft, s_szPrefix, sizeof(s_szPrefix) - 1); 1329 if (pszMarker) 1330 pszMarker += sizeof(s_szPrefix) - 1; 1331 else 1332 break; 1333 if (strncmp(pszMarker, RT_STR_TUPLE("START[")) != 0) 1334 return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, 1335 tr("Unexpected splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_%.64s"), 1336 pszFileToSplit, pszMarker - pszStart, pszMarker); 1337 pszMarker += sizeof("START[") - 1; 1338 const char *pszTail = splitFileLocateSubstring(pszMarker, pszEnd - pszMarker, RT_STR_TUPLE("]@@")); 1339 if ( !pszTail 1340 || pszTail - pszMarker > 64 1341 || memchr(pszMarker, '\\', pszTail - pszMarker) 1342 || memchr(pszMarker, '/', pszTail - pszMarker) 1343 || memchr(pszMarker, ':', pszTail - pszMarker) 1344 ) 1345 return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, 1346 tr("Malformed splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_START[%.64s"), 1347 pszFileToSplit, pszMarker - pszStart, pszMarker); 1348 int vrc = RTStrValidateEncodingEx(pszMarker, pszTail - pszMarker, RTSTR_VALIDATE_ENCODING_EXACT_LENGTH); 1349 if (RT_FAILURE(vrc)) 1350 return mpParent->setErrorBoth(E_FAIL, vrc, 1351 tr("Malformed splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_START[%.*Rhxs"), 1352 pszFileToSplit, pszMarker - pszStart, pszTail - pszMarker, pszMarker); 1353 const char *pszFilename; 1354 try 1355 { 1356 pszFilename = rVecSplitFiles.append().assign(pszMarker, pszTail - pszMarker).c_str(); 1357 } 1358 catch (std::bad_alloc &) 1359 { 1360 return E_OUTOFMEMORY; 1361 } 1362 const char *pszDocStart = pszTail + sizeof("]@@") - 1; 1363 while (RT_C_IS_SPACE(*pszDocStart)) 1364 if (*pszDocStart++ == '\n') 1365 break; 1366 1367 /* Advance. */ 1368 pszSrc = pszDocStart; 1369 cbLeft = pszEnd - pszDocStart; 1370 1371 /* 1372 * Locate the matching end marker (there cannot be any other markers inbetween). 1373 */ 1374 const char * const pszDocEnd = pszMarker = splitFileLocateSubstring(pszSrc, cbLeft, s_szPrefix, sizeof(s_szPrefix) - 1); 1375 if (pszMarker) 1376 pszMarker += sizeof(s_szPrefix) - 1; 1377 else 1378 return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, 1379 tr("No END splitter tag for '%s' in '%s'"), pszFilename, pszFileToSplit); 1380 if (strncmp(pszMarker, RT_STR_TUPLE("END[")) != 0) 1381 return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, 1382 tr("Unexpected splitter tag in '%s' at offset %p: @@VBOX_SPLITTER_%.64s"), 1383 pszFileToSplit, pszMarker - pszStart, pszMarker); 1384 pszMarker += sizeof("END[") - 1; 1385 size_t const cchFilename = strlen(pszFilename); 1386 if ( strncmp(pszMarker, pszFilename, cchFilename) != 0 1387 || pszMarker[cchFilename] != ']' 1388 || pszMarker[cchFilename + 1] != '@' 1389 || pszMarker[cchFilename + 2] != '@') 1390 return mpParent->setErrorBoth(E_FAIL, VERR_PARSE_ERROR, 1391 tr("Mismatching splitter tag for '%s' in '%s' at offset %p: @@VBOX_SPLITTER_END[%.64Rhxs"), 1392 pszFilename, pszFileToSplit, pszMarker - pszStart, pszMarker); 1393 1394 /* Advance. */ 1395 pszSrc = pszMarker + cchFilename + sizeof("]@@") - 1; 1396 cbLeft = pszEnd - pszSrc; 1397 1398 /* 1399 * Write out the file. 1400 */ 1401 Utf8Str strDstFilename; 1402 vrc = strDstFilename.assignNoThrow(mpParent->i_getAuxiliaryBasePath()); 1403 if (RT_SUCCESS(vrc)) 1404 vrc = strDstFilename.appendNoThrow(pszFilename); 1405 if (RT_SUCCESS(vrc)) 1406 { 1407 RTFILE hFile; 1408 vrc = RTFileOpen(&hFile, strDstFilename.c_str(), RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE); 1409 if (RT_SUCCESS(vrc)) 1410 { 1411 vrc = RTFileWrite(hFile, pszDocStart, pszDocEnd - pszDocStart, NULL); 1412 if (RT_SUCCESS(vrc)) 1413 vrc = RTFileClose(hFile); 1414 else 1415 RTFileClose(hFile); 1416 if (RT_FAILURE(vrc)) 1417 return mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error writing '%s' (split out from '%s'): %Rrc"), 1418 strDstFilename.c_str(), pszFileToSplit, vrc); 1419 } 1420 else 1421 return mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, 1422 tr("File splitter failed to open output file '%s' in '%s': %Rrc (%s)"), 1423 pszFilename, pszFileToSplit, vrc, strDstFilename.c_str()); 1424 } 1425 else 1426 return mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, 1427 tr("File splitter failed to construct path for '%s' in '%s': %Rrc"), 1428 pszFilename, pszFileToSplit, vrc); 1429 } 1430 1431 return S_OK; 1432 } 1433 1434 HRESULT UnattendedOs2Installer::splitFile(const char *pszFileToSplit, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT 1435 { 1436 /* 1437 * Read the whole source file into memory, making sure it's zero terminated. 1438 */ 1439 HRESULT hrc; 1440 void *pvSrc; 1441 size_t cbSrc; 1442 int vrc = RTFileReadAllEx(pszFileToSplit, 0 /*off*/, _16M /*cbMax*/, 1443 RTFILE_RDALL_F_TRAILING_ZERO_BYTE | RTFILE_RDALL_F_FAIL_ON_MAX_SIZE | RTFILE_RDALL_O_DENY_WRITE, 1444 &pvSrc, &cbSrc); 1445 if (RT_SUCCESS(vrc)) 1446 { 1447 /* 1448 * Do the actual splitting in a worker function to avoid needing to 1449 * thing about calling RTFileReadAllFree in error paths. 1450 */ 1451 hrc = splitFileInner(pszFileToSplit, rVecSplitFiles, (const char *)pvSrc, cbSrc); 1452 RTFileReadAllFree(pvSrc, cbSrc); 1453 } 1454 else 1455 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to read '%s' for splitting up: %Rrc"), 1456 pszFileToSplit, vrc); 1457 return hrc; 1458 } 1459 1460 HRESULT UnattendedOs2Installer::splitFile(BaseTextScript *pEditor, RTCList<RTCString> &rVecSplitFiles) RT_NOEXCEPT 1461 { 1462 /* 1463 * Get the output from the editor. 1464 */ 1465 Utf8Str strSrc; 1466 HRESULT hrc = pEditor->saveToString(strSrc); 1467 if (SUCCEEDED(hrc)) 1468 { 1469 /* 1470 * Do the actual splitting. 1471 */ 1472 hrc = splitFileInner(pEditor->getDefaultFilename(), rVecSplitFiles, strSrc.c_str(), strSrc.length()); 1473 } 1474 return hrc; 1475 } 1476 1477 1478 815 1479 ////////////////////////////////////////////////////////////////////////////////////////////////////// 816 1480 /* -
trunk/src/VBox/Main/src-server/UnattendedScript.cpp
r91502 r93085 59 59 static const char s_szPrefixCond[] = "@@VBOX_COND_"; 60 60 static const char s_szPrefixCondEnd[] = "@@VBOX_COND_END@@"; 61 static const char s_szPrefixSplitter[] = "@@VBOX_SPLITTER"; 61 62 62 63 struct … … 128 129 if ( pszPlaceholder[cchPlaceholder - 1] != '@' 129 130 || pszPlaceholder[cchPlaceholder - 2] != '@' 130 || ( strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) != 0 131 && strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) != 0 ) ) 131 || ( strncmp(pszPlaceholder, s_szPrefixInsert, sizeof(s_szPrefixInsert) - 1) != 0 132 && strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) != 0 133 && strncmp(pszPlaceholder, s_szPrefixSplitter, sizeof(s_szPrefixSplitter) - 1) != 0 ) ) 132 134 { 133 135 hrc = mpSetError->setError(E_FAIL, tr("Malformed template placeholder '%.*s'"), … … 188 190 * one from the condition. 189 191 */ 190 else 192 else if (strncmp(pszPlaceholder, s_szPrefixSplitter, sizeof(s_szPrefixSplitter) - 1) != 0) 191 193 { 192 194 Assert(strncmp(pszPlaceholder, s_szPrefixCond, sizeof(s_szPrefixCond) - 1) == 0); … … 208 210 offPlaceholder, offPlaceholder); 209 211 break; 212 } 213 } 214 /* 215 * @@VBOX_SPLITTER_START/END[filename]@@: Ignored in this pass. 216 */ 217 else 218 { 219 if (fOutputting) 220 { 221 try 222 { 223 rStrDst.append(pszPlaceholder, cchPlaceholder); 224 } 225 catch (std::bad_alloc &) 226 { 227 hrc = E_OUTOFMEMORY; 228 break; 229 } 210 230 } 211 231 }
Note:
See TracChangeset
for help on using the changeset viewer.