VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/UnattendedInstaller.cpp@ 93082

最後變更 在這個檔案從93082是 93082,由 vboxsync 提交於 3 年 前

Main/Unattended: Detect OS/2 ISOs.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 46.1 KB
 
1/* $Id: UnattendedInstaller.cpp 93082 2021-12-26 01:27:48Z vboxsync $ */
2/** @file
3 * UnattendedInstaller class and it's descendants implementation
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_MAIN_UNATTENDED
23#include "LoggingNew.h"
24#include "VirtualBoxBase.h"
25#include "VirtualBoxErrorInfoImpl.h"
26#include "AutoCaller.h"
27#include <VBox/com/ErrorInfo.h>
28
29#include "UnattendedImpl.h"
30#include "UnattendedInstaller.h"
31#include "UnattendedScript.h"
32
33#include <VBox/err.h>
34#include <iprt/ctype.h>
35#include <iprt/fsisomaker.h>
36#include <iprt/fsvfs.h>
37#include <iprt/getopt.h>
38#include <iprt/file.h>
39#include <iprt/path.h>
40#include <iprt/stream.h>
41#include <iprt/vfs.h>
42#ifdef RT_OS_SOLARIS
43# undef ES /* Workaround for someone dragging the namespace pollutor sys/regset.h. Sigh. */
44#endif
45#include <iprt/formats/iso9660.h>
46#include <iprt/cpp/path.h>
47
48
49using namespace std;
50
51
52/* static */ UnattendedInstaller *UnattendedInstaller::createInstance(VBOXOSTYPE enmOsType,
53 const Utf8Str &strGuestOsType,
54 const Utf8Str &strDetectedOSVersion,
55 const Utf8Str &strDetectedOSFlavor,
56 const Utf8Str &strDetectedOSHints,
57 Unattended *pParent)
58{
59 UnattendedInstaller *pUinstaller = NULL;
60
61 if (strGuestOsType.find("Windows") != RTCString::npos)
62 {
63 if (enmOsType >= VBOXOSTYPE_WinVista)
64 pUinstaller = new UnattendedWindowsXmlInstaller(pParent);
65 else
66 pUinstaller = new UnattendedWindowsSifInstaller(pParent);
67 }
68 else if (enmOsType >= VBOXOSTYPE_OS2 && enmOsType < VBOXOSTYPE_Linux)
69 {
70 /** @todo OS/2 */
71 }
72 else
73 {
74 if (enmOsType == VBOXOSTYPE_Debian || enmOsType == VBOXOSTYPE_Debian_x64)
75 pUinstaller = new UnattendedDebianInstaller(pParent);
76 else if (enmOsType >= VBOXOSTYPE_Ubuntu && enmOsType <= VBOXOSTYPE_Ubuntu_x64)
77 pUinstaller = new UnattendedUbuntuInstaller(pParent);
78 else if (enmOsType >= VBOXOSTYPE_RedHat && enmOsType <= VBOXOSTYPE_RedHat_x64)
79 {
80 if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "8") >= 0)
81 pUinstaller = new UnattendedRhel8Installer(pParent);
82 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "7") >= 0)
83 pUinstaller = new UnattendedRhel7Installer(pParent);
84 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "6") >= 0)
85 pUinstaller = new UnattendedRhel6Installer(pParent);
86 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "5") >= 0)
87 pUinstaller = new UnattendedRhel5Installer(pParent);
88 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "4") >= 0)
89 pUinstaller = new UnattendedRhel4Installer(pParent);
90 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "3") >= 0)
91 pUinstaller = new UnattendedRhel3Installer(pParent);
92 else
93 pUinstaller = new UnattendedRhel6Installer(pParent);
94 }
95 else if (enmOsType >= VBOXOSTYPE_FedoraCore && enmOsType <= VBOXOSTYPE_FedoraCore_x64)
96 pUinstaller = new UnattendedFedoraInstaller(pParent);
97 else if (enmOsType >= VBOXOSTYPE_Oracle && enmOsType <= VBOXOSTYPE_Oracle_x64)
98 {
99 if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "8") >= 0)
100 pUinstaller = new UnattendedOracleLinux8Installer(pParent);
101 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "7") >= 0)
102 pUinstaller = new UnattendedOracleLinux7Installer(pParent);
103 else if (RTStrVersionCompare(strDetectedOSVersion.c_str(), "6") >= 0)
104 pUinstaller = new UnattendedOracleLinux6Installer(pParent);
105 else
106 pUinstaller = new UnattendedOracleLinux6Installer(pParent);
107 }
108#if 0 /* doesn't work, so convert later. */
109 else if (enmOsType == VBOXOSTYPE_OpenSUSE || enmOsType == VBOXOSTYPE_OpenSUSE_x64)
110 pUinstaller = new UnattendedSuseInstaller(new UnattendedSUSEXMLScript(pParent), pParent);
111#endif
112 }
113 RT_NOREF_PV(strDetectedOSFlavor);
114 RT_NOREF_PV(strDetectedOSHints);
115 return pUinstaller;
116}
117
118
119//////////////////////////////////////////////////////////////////////////////////////////////////////
120/*
121*
122*
123* Implementation Unattended functions
124*
125*/
126//////////////////////////////////////////////////////////////////////////////////////////////////////
127
128/*
129 *
130 * UnattendedInstaller public methods
131 *
132 */
133UnattendedInstaller::UnattendedInstaller(Unattended *pParent,
134 const char *pszMainScriptTemplateName, const char *pszPostScriptTemplateName,
135 const char *pszMainScriptFilename, const char *pszPostScriptFilename,
136 DeviceType_T enmBootDevice /*= DeviceType_DVD */)
137 : mMainScript(pParent, pszMainScriptTemplateName, pszMainScriptFilename)
138 , mPostScript(pParent, pszPostScriptTemplateName, pszPostScriptFilename)
139 , mpParent(pParent)
140 , meBootDevice(enmBootDevice)
141{
142 AssertPtr(pParent);
143 Assert(*pszMainScriptTemplateName);
144 Assert(*pszMainScriptFilename);
145 Assert(*pszPostScriptTemplateName);
146 Assert(*pszPostScriptFilename);
147 Assert(enmBootDevice == DeviceType_DVD || enmBootDevice == DeviceType_Floppy);
148}
149
150UnattendedInstaller::~UnattendedInstaller()
151{
152 mpParent = NULL;
153}
154
155HRESULT UnattendedInstaller::initInstaller()
156{
157 /*
158 * Calculate the full main script template location.
159 */
160 if (mpParent->i_getScriptTemplatePath().isNotEmpty())
161 mStrMainScriptTemplate = mpParent->i_getScriptTemplatePath();
162 else
163 {
164 int vrc = RTPathAppPrivateNoArchCxx(mStrMainScriptTemplate);
165 if (RT_SUCCESS(vrc))
166 vrc = RTPathAppendCxx(mStrMainScriptTemplate, "UnattendedTemplates");
167 if (RT_SUCCESS(vrc))
168 vrc = RTPathAppendCxx(mStrMainScriptTemplate, mMainScript.getDefaultTemplateFilename());
169 if (RT_FAILURE(vrc))
170 return mpParent->setErrorBoth(E_FAIL, vrc,
171 tr("Failed to construct path to the unattended installer script templates (%Rrc)"),
172 vrc);
173 }
174
175 /*
176 * Calculate the full post script template location.
177 */
178 if (mpParent->i_getPostInstallScriptTemplatePath().isNotEmpty())
179 mStrPostScriptTemplate = mpParent->i_getPostInstallScriptTemplatePath();
180 else
181 {
182 int vrc = RTPathAppPrivateNoArchCxx(mStrPostScriptTemplate);
183 if (RT_SUCCESS(vrc))
184 vrc = RTPathAppendCxx(mStrPostScriptTemplate, "UnattendedTemplates");
185 if (RT_SUCCESS(vrc))
186 vrc = RTPathAppendCxx(mStrPostScriptTemplate, mPostScript.getDefaultTemplateFilename());
187 if (RT_FAILURE(vrc))
188 return mpParent->setErrorBoth(E_FAIL, vrc,
189 tr("Failed to construct path to the unattended installer script templates (%Rrc)"),
190 vrc);
191 }
192
193 /*
194 * Construct paths we need.
195 */
196 if (isAuxiliaryFloppyNeeded())
197 {
198 mStrAuxiliaryFloppyFilePath = mpParent->i_getAuxiliaryBasePath();
199 mStrAuxiliaryFloppyFilePath.append("aux-floppy.img");
200 }
201 if (isAuxiliaryIsoNeeded())
202 {
203 mStrAuxiliaryIsoFilePath = mpParent->i_getAuxiliaryBasePath();
204 if (!isAuxiliaryIsoIsVISO())
205 mStrAuxiliaryIsoFilePath.append("aux-iso.iso");
206 else
207 mStrAuxiliaryIsoFilePath.append("aux-iso.viso");
208 }
209
210 /*
211 * Check that we've got the minimum of data available.
212 */
213 if (mpParent->i_getIsoPath().isEmpty())
214 return mpParent->setError(E_INVALIDARG, tr("Cannot proceed with an empty installation ISO path"));
215 if (mpParent->i_getUser().isEmpty())
216 return mpParent->setError(E_INVALIDARG, tr("Empty user name is not allowed"));
217 if (mpParent->i_getPassword().isEmpty())
218 return mpParent->setError(E_INVALIDARG, tr("Empty password is not allowed"));
219
220 LogRelFunc(("UnattendedInstaller::savePassedData(): \n"));
221 return S_OK;
222}
223
224#if 0 /* Always in AUX ISO */
225bool UnattendedInstaller::isAdditionsIsoNeeded() const
226{
227 /* In the VISO case, we'll add the additions to the VISO in a subdir. */
228 return !isAuxiliaryIsoIsVISO() && mpParent->i_getInstallGuestAdditions();
229}
230
231bool UnattendedInstaller::isValidationKitIsoNeeded() const
232{
233 /* In the VISO case, we'll add the validation kit to the VISO in a subdir. */
234 return !isAuxiliaryIsoIsVISO() && mpParent->i_getInstallTestExecService();
235}
236#endif
237
238bool UnattendedInstaller::isAuxiliaryIsoNeeded() const
239{
240 /* In the VISO case we use the AUX ISO for GAs and TXS. */
241 return isAuxiliaryIsoIsVISO()
242 && ( mpParent->i_getInstallGuestAdditions()
243 || mpParent->i_getInstallTestExecService());
244}
245
246
247HRESULT UnattendedInstaller::prepareUnattendedScripts()
248{
249 LogFlow(("UnattendedInstaller::prepareUnattendedScripts()\n"));
250
251 /*
252 * The script template editor calls setError, so status codes just needs to
253 * be passed on to the caller. Do the same for both scripts.
254 */
255 HRESULT hrc = mMainScript.read(getTemplateFilePath());
256 if (SUCCEEDED(hrc))
257 {
258 hrc = mMainScript.parse();
259 if (SUCCEEDED(hrc))
260 {
261 /* Ditto for the post script. */
262 hrc = mPostScript.read(getPostTemplateFilePath());
263 if (SUCCEEDED(hrc))
264 {
265 hrc = mPostScript.parse();
266 if (SUCCEEDED(hrc))
267 {
268 LogFlow(("UnattendedInstaller::prepareUnattendedScripts: returns S_OK\n"));
269 return S_OK;
270 }
271 LogFlow(("UnattendedInstaller::prepareUnattendedScripts: parse failed on post script (%Rhrc)\n", hrc));
272 }
273 else
274 LogFlow(("UnattendedInstaller::prepareUnattendedScripts: error reading post install script template file (%Rhrc)\n", hrc));
275 }
276 else
277 LogFlow(("UnattendedInstaller::prepareUnattendedScripts: parse failed (%Rhrc)\n", hrc));
278 }
279 else
280 LogFlow(("UnattendedInstaller::prepareUnattendedScripts: error reading installation script template file (%Rhrc)\n", hrc));
281 return hrc;
282}
283
284HRESULT UnattendedInstaller::prepareMedia(bool fOverwrite /*=true*/)
285{
286 LogRelFlow(("UnattendedInstaller::prepareMedia:\n"));
287 HRESULT hrc = S_OK;
288 if (isAuxiliaryFloppyNeeded())
289 hrc = prepareAuxFloppyImage(fOverwrite);
290 if (SUCCEEDED(hrc))
291 {
292 if (isAuxiliaryIsoNeeded())
293 {
294 hrc = prepareAuxIsoImage(fOverwrite);
295 if (FAILED(hrc))
296 {
297 LogRelFlow(("UnattendedInstaller::prepareMedia: prepareAuxIsoImage failed\n"));
298
299 /* Delete the floppy image if we created one. */
300 if (isAuxiliaryFloppyNeeded())
301 RTFileDelete(getAuxiliaryFloppyFilePath().c_str());
302 }
303 }
304 }
305 LogRelFlow(("UnattendedInstaller::prepareMedia: returns %Rrc\n", hrc));
306 return hrc;
307}
308
309/*
310 *
311 * UnattendedInstaller protected methods
312 *
313 */
314HRESULT UnattendedInstaller::prepareAuxFloppyImage(bool fOverwrite)
315{
316 Assert(isAuxiliaryFloppyNeeded());
317
318 /*
319 * Create the image and get a VFS to it.
320 */
321 RTVFS hVfs;
322 HRESULT hrc = newAuxFloppyImage(getAuxiliaryFloppyFilePath().c_str(), fOverwrite, &hVfs);
323 if (SUCCEEDED(hrc))
324 {
325 /*
326 * Call overridable method to copies the files onto it.
327 */
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
336 if (FAILED(hrc))
337 RTFileDelete(getAuxiliaryFloppyFilePath().c_str());
338 }
339 return hrc;
340}
341
342HRESULT UnattendedInstaller::newAuxFloppyImage(const char *pszFilename, bool fOverwrite, PRTVFS phVfs)
343{
344 /*
345 * Open the image file.
346 */
347 HRESULT hrc;
348 RTVFSFILE hVfsFile;
349 uint64_t fOpen = RTFILE_O_READWRITE | RTFILE_O_DENY_ALL | (0660 << RTFILE_O_CREATE_MODE_SHIFT);
350 if (fOverwrite)
351 fOpen |= RTFILE_O_CREATE_REPLACE;
352 else
353 fOpen |= RTFILE_O_OPEN;
354 int vrc = RTVfsFileOpenNormal(pszFilename, fOpen, &hVfsFile);
355 if (RT_SUCCESS(vrc))
356 {
357 /*
358 * Format it.
359 */
360 vrc = RTFsFatVolFormat144(hVfsFile, false /*fQuick*/);
361 if (RT_SUCCESS(vrc))
362 {
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);
386 RTVfsFileRelease(hVfsFile);
387 RTFileDelete(pszFilename);
388 }
389 else
390 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to create floppy image '%s': %Rrc"), pszFilename, vrc);
391 return hrc;
392}
393
394
395HRESULT UnattendedInstaller::copyFilesToAuxFloppyImage(RTVFS hVfs)
396{
397 HRESULT hrc = addScriptToFloppyImage(&mMainScript, hVfs);
398 if (SUCCEEDED(hrc))
399 hrc = addScriptToFloppyImage(&mPostScript, hVfs);
400 return hrc;
401}
402
403HRESULT UnattendedInstaller::addScriptToFloppyImage(BaseTextScript *pEditor, RTVFS hVfs)
404{
405 /*
406 * Open the destination file.
407 */
408 HRESULT hrc;
409 RTVFSFILE hVfsFileDst;
410 int vrc = RTVfsFileOpen(hVfs, pEditor->getDefaultFilename(),
411 RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_ALL
412 | (0660 << RTFILE_O_CREATE_MODE_SHIFT),
413 &hVfsFileDst);
414 if (RT_SUCCESS(vrc))
415 {
416 /*
417 * Save the content to a string.
418 */
419 Utf8Str strScript;
420 hrc = pEditor->saveToString(strScript);
421 if (SUCCEEDED(hrc))
422 {
423 /*
424 * Write the string.
425 */
426 vrc = RTVfsFileWrite(hVfsFileDst, strScript.c_str(), strScript.length(), NULL);
427 if (RT_SUCCESS(vrc))
428 hrc = S_OK; /* done */
429 else
430 hrc = mpParent->setErrorBoth(E_FAIL, vrc,
431 tr("Error writing %zu bytes to '%s' in floppy image '%s': %Rrc",
432 "", strScript.length()),
433 strScript.length(), pEditor->getDefaultFilename(),
434 getAuxiliaryFloppyFilePath().c_str());
435 }
436 RTVfsFileRelease(hVfsFileDst);
437 }
438 else
439 hrc = mpParent->setErrorBoth(E_FAIL, vrc,
440 tr("Error creating '%s' in floppy image '%s': %Rrc"),
441 pEditor->getDefaultFilename(), getAuxiliaryFloppyFilePath().c_str());
442 return hrc;
443
444}
445
446HRESULT UnattendedInstaller::prepareAuxIsoImage(bool fOverwrite)
447{
448 /*
449 * Open the original installation ISO.
450 */
451 RTVFS hVfsOrgIso;
452 HRESULT hrc = openInstallIsoImage(&hVfsOrgIso);
453 if (SUCCEEDED(hrc))
454 {
455 /*
456 * The next steps depends on the kind of image we're making.
457 */
458 if (!isAuxiliaryIsoIsVISO())
459 {
460 RTFSISOMAKER hIsoMaker;
461 hrc = newAuxIsoImageMaker(&hIsoMaker);
462 if (SUCCEEDED(hrc))
463 {
464 hrc = addFilesToAuxIsoImageMaker(hIsoMaker, hVfsOrgIso);
465 if (SUCCEEDED(hrc))
466 hrc = finalizeAuxIsoImage(hIsoMaker, getAuxiliaryIsoFilePath().c_str(), fOverwrite);
467 RTFsIsoMakerRelease(hIsoMaker);
468 }
469 }
470 else
471 {
472 RTCList<RTCString> vecFiles(0);
473 RTCList<RTCString> vecArgs(0);
474 try
475 {
476 vecArgs.append() = "--iprt-iso-maker-file-marker-bourne-sh";
477 RTUUID Uuid;
478 int vrc = RTUuidCreate(&Uuid); AssertRC(vrc);
479 char szTmp[RTUUID_STR_LENGTH + 1];
480 vrc = RTUuidToStr(&Uuid, szTmp, sizeof(szTmp)); AssertRC(vrc);
481 vecArgs.append() = szTmp;
482 vecArgs.append() = "--file-mode=0444";
483 vecArgs.append() = "--dir-mode=0555";
484 }
485 catch (std::bad_alloc &)
486 {
487 hrc = E_OUTOFMEMORY;
488 }
489 if (SUCCEEDED(hrc))
490 {
491 hrc = addFilesToAuxVisoVectors(vecArgs, vecFiles, hVfsOrgIso, fOverwrite);
492 if (SUCCEEDED(hrc))
493 hrc = finalizeAuxVisoFile(vecArgs, getAuxiliaryIsoFilePath().c_str(), fOverwrite);
494
495 if (FAILED(hrc))
496 for (size_t i = 0; i < vecFiles.size(); i++)
497 RTFileDelete(vecFiles[i].c_str());
498 }
499 }
500 RTVfsRelease(hVfsOrgIso);
501 }
502 return hrc;
503}
504
505HRESULT UnattendedInstaller::openInstallIsoImage(PRTVFS phVfsIso, uint32_t fFlags /*= 0*/)
506{
507 /* Open the file. */
508 const char *pszIsoPath = mpParent->i_getIsoPath().c_str();
509 RTVFSFILE hOrgIsoFile;
510 int vrc = RTVfsFileOpenNormal(pszIsoPath, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &hOrgIsoFile);
511 if (RT_FAILURE(vrc))
512 return mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to open ISO image '%s' (%Rrc)"), pszIsoPath, vrc);
513
514 /* Pass the file to the ISO file system interpreter. */
515 RTERRINFOSTATIC ErrInfo;
516 vrc = RTFsIso9660VolOpen(hOrgIsoFile, fFlags, phVfsIso, RTErrInfoInitStatic(&ErrInfo));
517 RTVfsFileRelease(hOrgIsoFile);
518 if (RT_SUCCESS(vrc))
519 return S_OK;
520 if (RTErrInfoIsSet(&ErrInfo.Core))
521 return mpParent->setErrorBoth(E_FAIL, vrc, tr("ISO reader fail to open '%s' (%Rrc): %s"),
522 pszIsoPath, vrc, ErrInfo.Core.pszMsg);
523 return mpParent->setErrorBoth(E_FAIL, vrc, tr("ISO reader fail to open '%s' (%Rrc)"), pszIsoPath, vrc);
524}
525
526HRESULT UnattendedInstaller::newAuxIsoImageMaker(PRTFSISOMAKER phIsoMaker)
527{
528 int vrc = RTFsIsoMakerCreate(phIsoMaker);
529 if (RT_SUCCESS(vrc))
530 return S_OK;
531 return mpParent->setErrorBoth(E_FAIL, vrc, tr("RTFsIsoMakerCreate failed (%Rrc)"), vrc);
532}
533
534HRESULT UnattendedInstaller::addFilesToAuxIsoImageMaker(RTFSISOMAKER hIsoMaker, RTVFS hVfsOrgIso)
535{
536 RT_NOREF(hVfsOrgIso);
537
538 /*
539 * Add the two scripts to the image with default names.
540 */
541 HRESULT hrc = addScriptToIsoMaker(&mMainScript, hIsoMaker);
542 if (SUCCEEDED(hrc))
543 hrc = addScriptToIsoMaker(&mPostScript, hIsoMaker);
544 return hrc;
545}
546
547HRESULT UnattendedInstaller::addScriptToIsoMaker(BaseTextScript *pEditor, RTFSISOMAKER hIsoMaker,
548 const char *pszDstFilename /*= NULL*/)
549{
550 /*
551 * Calc default destination filename if desired.
552 */
553 RTCString strDstNameBuf;
554 if (!pszDstFilename)
555 {
556 try
557 {
558 strDstNameBuf = RTPATH_SLASH_STR;
559 strDstNameBuf.append(pEditor->getDefaultTemplateFilename());
560 pszDstFilename = strDstNameBuf.c_str();
561 }
562 catch (std::bad_alloc &)
563 {
564 return E_OUTOFMEMORY;
565 }
566 }
567
568 /*
569 * Create a memory file for the script.
570 */
571 Utf8Str strScript;
572 HRESULT hrc = pEditor->saveToString(strScript);
573 if (SUCCEEDED(hrc))
574 {
575 RTVFSFILE hVfsScriptFile;
576 size_t cchScript = strScript.length();
577 int vrc = RTVfsFileFromBuffer(RTFILE_O_READ, strScript.c_str(), strScript.length(), &hVfsScriptFile);
578 strScript.setNull();
579 if (RT_SUCCESS(vrc))
580 {
581 /*
582 * Add it to the ISO.
583 */
584 vrc = RTFsIsoMakerAddFileWithVfsFile(hIsoMaker, pszDstFilename, hVfsScriptFile, NULL);
585 RTVfsFileRelease(hVfsScriptFile);
586 if (RT_SUCCESS(vrc))
587 hrc = S_OK;
588 else
589 hrc = mpParent->setErrorBoth(E_FAIL, vrc,
590 tr("RTFsIsoMakerAddFileWithVfsFile failed on the script '%s' (%Rrc)"),
591 pszDstFilename, vrc);
592 }
593 else
594 hrc = mpParent->setErrorBoth(E_FAIL, vrc,
595 tr("RTVfsFileFromBuffer failed on the %zu byte script '%s' (%Rrc)", "", cchScript),
596 cchScript, pszDstFilename, vrc);
597 }
598 return hrc;
599}
600
601HRESULT UnattendedInstaller::finalizeAuxIsoImage(RTFSISOMAKER hIsoMaker, const char *pszFilename, bool fOverwrite)
602{
603 /*
604 * Finalize the image.
605 */
606 int vrc = RTFsIsoMakerFinalize(hIsoMaker);
607 if (RT_FAILURE(vrc))
608 return mpParent->setErrorBoth(E_FAIL, vrc, tr("RTFsIsoMakerFinalize failed (%Rrc)"), vrc);
609
610 /*
611 * Open the destination file.
612 */
613 uint64_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_ALL;
614 if (fOverwrite)
615 fOpen |= RTFILE_O_CREATE_REPLACE;
616 else
617 fOpen |= RTFILE_O_CREATE;
618 RTVFSFILE hVfsDstFile;
619 vrc = RTVfsFileOpenNormal(pszFilename, fOpen, &hVfsDstFile);
620 if (RT_FAILURE(vrc))
621 {
622 if (vrc == VERR_ALREADY_EXISTS)
623 return mpParent->setErrorBoth(E_FAIL, vrc, tr("The auxiliary ISO image file '%s' already exists"),
624 pszFilename);
625 return mpParent->setErrorBoth(E_FAIL, vrc, tr("Failed to open the auxiliary ISO image file '%s' for writing (%Rrc)"),
626 pszFilename, vrc);
627 }
628
629 /*
630 * Get the source file from the image maker.
631 */
632 HRESULT hrc;
633 RTVFSFILE hVfsSrcFile;
634 vrc = RTFsIsoMakerCreateVfsOutputFile(hIsoMaker, &hVfsSrcFile);
635 if (RT_SUCCESS(vrc))
636 {
637 RTVFSIOSTREAM hVfsSrcIso = RTVfsFileToIoStream(hVfsSrcFile);
638 RTVFSIOSTREAM hVfsDstIso = RTVfsFileToIoStream(hVfsDstFile);
639 if ( hVfsSrcIso != NIL_RTVFSIOSTREAM
640 && hVfsDstIso != NIL_RTVFSIOSTREAM)
641 {
642 vrc = RTVfsUtilPumpIoStreams(hVfsSrcIso, hVfsDstIso, 0 /*cbBufHint*/);
643 if (RT_SUCCESS(vrc))
644 hrc = S_OK;
645 else
646 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("Error writing auxiliary ISO image '%s' (%Rrc)"),
647 pszFilename, vrc);
648 }
649 else
650 hrc = mpParent->setErrorBoth(E_FAIL, VERR_INTERNAL_ERROR_2,
651 tr("Internal Error: Failed to case VFS file to VFS I/O stream"));
652 RTVfsIoStrmRelease(hVfsSrcIso);
653 RTVfsIoStrmRelease(hVfsDstIso);
654 }
655 else
656 hrc = mpParent->setErrorBoth(E_FAIL, vrc, tr("RTFsIsoMakerCreateVfsOutputFile failed (%Rrc)"), vrc);
657 RTVfsFileRelease(hVfsSrcFile);
658 RTVfsFileRelease(hVfsDstFile);
659 if (FAILED(hrc))
660 RTFileDelete(pszFilename);
661 return hrc;
662}
663
664HRESULT UnattendedInstaller::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
665 RTVFS hVfsOrgIso, bool fOverwrite)
666{
667 RT_NOREF(hVfsOrgIso);
668
669 /*
670 * Save and add the scripts.
671 */
672 HRESULT hrc = addScriptToVisoVectors(&mMainScript, rVecArgs, rVecFiles, fOverwrite);
673 if (SUCCEEDED(hrc))
674 hrc = addScriptToVisoVectors(&mPostScript, rVecArgs, rVecFiles, fOverwrite);
675 if (SUCCEEDED(hrc))
676 {
677 try
678 {
679 /*
680 * If we've got a Guest Additions ISO, add its content to a /vboxadditions dir.
681 */
682 if (mpParent->i_getInstallGuestAdditions())
683 {
684 rVecArgs.append().append("--push-iso=").append(mpParent->i_getAdditionsIsoPath());
685 rVecArgs.append() = "/vboxadditions=/";
686 rVecArgs.append() = "--pop";
687 }
688
689 /*
690 * If we've got a Validation Kit ISO, add its content to a /vboxvalidationkit dir.
691 */
692 if (mpParent->i_getInstallTestExecService())
693 {
694 rVecArgs.append().append("--push-iso=").append(mpParent->i_getValidationKitIsoPath());
695 rVecArgs.append() = "/vboxvalidationkit=/";
696 rVecArgs.append() = "--pop";
697 }
698 }
699 catch (std::bad_alloc &)
700 {
701 hrc = E_OUTOFMEMORY;
702 }
703 }
704 return hrc;
705}
706
707HRESULT UnattendedInstaller::addScriptToVisoVectors(BaseTextScript *pEditor, RTCList<RTCString> &rVecArgs,
708 RTCList<RTCString> &rVecFiles, bool fOverwrite)
709{
710 /*
711 * Calc the aux script file name.
712 */
713 RTCString strScriptName;
714 try
715 {
716 strScriptName = mpParent->i_getAuxiliaryBasePath();
717 strScriptName.append(pEditor->getDefaultFilename());
718 }
719 catch (std::bad_alloc &)
720 {
721 return E_OUTOFMEMORY;
722 }
723
724 /*
725 * Save it.
726 */
727 HRESULT hrc = pEditor->save(strScriptName.c_str(), fOverwrite);
728 if (SUCCEEDED(hrc))
729 {
730 /*
731 * Add it to the vectors.
732 */
733 try
734 {
735 rVecArgs.append().append('/').append(pEditor->getDefaultFilename()).append('=').append(strScriptName);
736 rVecFiles.append(strScriptName);
737 }
738 catch (std::bad_alloc &)
739 {
740 RTFileDelete(strScriptName.c_str());
741 hrc = E_OUTOFMEMORY;
742 }
743 }
744 return hrc;
745}
746
747HRESULT UnattendedInstaller::finalizeAuxVisoFile(RTCList<RTCString> const &rVecArgs, const char *pszFilename, bool fOverwrite)
748{
749 /*
750 * Create a C-style argument vector and turn that into a command line string.
751 */
752 size_t const cArgs = rVecArgs.size();
753 const char **papszArgs = (const char **)RTMemTmpAlloc((cArgs + 1) * sizeof(const char *));
754 if (!papszArgs)
755 return E_OUTOFMEMORY;
756 for (size_t i = 0; i < cArgs; i++)
757 papszArgs[i] = rVecArgs[i].c_str();
758 papszArgs[cArgs] = NULL;
759
760 char *pszCmdLine;
761 int vrc = RTGetOptArgvToString(&pszCmdLine, papszArgs, RTGETOPTARGV_CNV_QUOTE_BOURNE_SH);
762 RTMemTmpFree(papszArgs);
763 if (RT_FAILURE(vrc))
764 return mpParent->setErrorBoth(E_FAIL, vrc, tr("RTGetOptArgvToString failed (%Rrc)"), vrc);
765
766 /*
767 * Open the file.
768 */
769 HRESULT hrc;
770 uint64_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_DENY_READ;
771 if (fOverwrite)
772 fOpen |= RTFILE_O_CREATE_REPLACE;
773 else
774 fOpen |= RTFILE_O_CREATE;
775 RTFILE hFile;
776 vrc = RTFileOpen(&hFile, pszFilename, fOpen);
777 if (RT_SUCCESS(vrc))
778 {
779 vrc = RTFileWrite(hFile, pszCmdLine, strlen(pszCmdLine), NULL);
780 if (RT_SUCCESS(vrc))
781 vrc = RTFileClose(hFile);
782 else
783 RTFileClose(hFile);
784 if (RT_SUCCESS(vrc))
785 hrc = S_OK;
786 else
787 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Error writing '%s' (%Rrc)"), pszFilename, vrc);
788 }
789 else
790 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to create '%s' (%Rrc)"), pszFilename, vrc);
791
792 RTStrFree(pszCmdLine);
793 return hrc;
794}
795
796HRESULT UnattendedInstaller::loadAndParseFileFromIso(RTVFS hVfsOrgIso, const char *pszFilename, AbstractScript *pEditor)
797{
798 HRESULT hrc;
799 RTVFSFILE hVfsFile;
800 int vrc = RTVfsFileOpen(hVfsOrgIso, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, &hVfsFile);
801 if (RT_SUCCESS(vrc))
802 {
803 hrc = pEditor->readFromHandle(hVfsFile, pszFilename);
804 RTVfsFileRelease(hVfsFile);
805 if (SUCCEEDED(hrc))
806 hrc = pEditor->parse();
807 }
808 else
809 hrc = mpParent->setErrorBoth(VBOX_E_FILE_ERROR, vrc, tr("Failed to open '%s' on the ISO '%s' (%Rrc)"),
810 pszFilename, mpParent->i_getIsoPath().c_str(), vrc);
811 return hrc;
812}
813
814
815//////////////////////////////////////////////////////////////////////////////////////////////////////
816/*
817*
818*
819* Implementation UnattendedLinuxInstaller functions
820*
821*/
822//////////////////////////////////////////////////////////////////////////////////////////////////////
823HRESULT UnattendedLinuxInstaller::editIsoLinuxCfg(GeneralTextScript *pEditor)
824{
825 try
826 {
827 /* Set timeouts to 10 seconds. */
828 std::vector<size_t> vecLineNumbers = pEditor->findTemplate("timeout", RTCString::CaseInsensitive);
829 for (size_t i = 0; i < vecLineNumbers.size(); ++i)
830 if (pEditor->getContentOfLine(vecLineNumbers[i]).startsWithWord("timeout", RTCString::CaseInsensitive))
831 {
832 HRESULT hrc = pEditor->setContentOfLine(vecLineNumbers.at(i), "timeout 10");
833 if (FAILED(hrc))
834 return hrc;
835 }
836
837 /* Comment out 'display <filename>' directives that's used for displaying files at boot time. */
838 vecLineNumbers = pEditor->findTemplate("display", RTCString::CaseInsensitive);
839 for (size_t i = 0; i < vecLineNumbers.size(); ++i)
840 if (pEditor->getContentOfLine(vecLineNumbers[i]).startsWithWord("display", RTCString::CaseInsensitive))
841 {
842 HRESULT hrc = pEditor->prependToLine(vecLineNumbers.at(i), "#");
843 if (FAILED(hrc))
844 return hrc;
845 }
846
847 /* Modify kernel parameters. */
848 vecLineNumbers = pEditor->findTemplate("append", RTCString::CaseInsensitive);
849 if (vecLineNumbers.size() > 0)
850 {
851 Utf8Str const &rStrAppend = mpParent->i_getExtraInstallKernelParameters().isNotEmpty()
852 ? mpParent->i_getExtraInstallKernelParameters()
853 : mStrDefaultExtraInstallKernelParameters;
854
855 for (size_t i = 0; i < vecLineNumbers.size(); ++i)
856 if (pEditor->getContentOfLine(vecLineNumbers[i]).startsWithWord("append", RTCString::CaseInsensitive))
857 {
858 Utf8Str strLine = pEditor->getContentOfLine(vecLineNumbers[i]);
859
860 /* Do removals. */
861 if (mArrStrRemoveInstallKernelParameters.size() > 0)
862 {
863 size_t offStart = strLine.find("append") + 5;
864 while (offStart < strLine.length() && !RT_C_IS_SPACE(strLine[offStart]))
865 offStart++;
866 while (offStart < strLine.length() && RT_C_IS_SPACE(strLine[offStart]))
867 offStart++;
868 if (offStart < strLine.length())
869 {
870 for (size_t iRemove = 0; iRemove < mArrStrRemoveInstallKernelParameters.size(); iRemove++)
871 {
872 RTCString const &rStrRemove = mArrStrRemoveInstallKernelParameters[iRemove];
873 for (size_t off = offStart; off < strLine.length(); )
874 {
875 Assert(!RT_C_IS_SPACE(strLine[off]));
876
877 /* Find the end of word. */
878 size_t offEnd = off + 1;
879 while (offEnd < strLine.length() && !RT_C_IS_SPACE(strLine[offEnd]))
880 offEnd++;
881
882 /* Check if it matches. */
883 if (RTStrSimplePatternNMatch(rStrRemove.c_str(), rStrRemove.length(),
884 strLine.c_str() + off, offEnd - off))
885 {
886 while (off > 0 && RT_C_IS_SPACE(strLine[off - 1]))
887 off--;
888 strLine.erase(off, offEnd - off);
889 }
890
891 /* Advance to the next word. */
892 off = offEnd;
893 while (off < strLine.length() && RT_C_IS_SPACE(strLine[off]))
894 off++;
895 }
896 }
897 }
898 }
899
900 /* Do the appending. */
901 if (rStrAppend.isNotEmpty())
902 {
903 if (!rStrAppend.startsWith(" ") && !strLine.endsWith(" "))
904 strLine.append(' ');
905 strLine.append(rStrAppend);
906 }
907
908 /* Update line. */
909 HRESULT hrc = pEditor->setContentOfLine(vecLineNumbers.at(i), strLine);
910 if (FAILED(hrc))
911 return hrc;
912 }
913 }
914 }
915 catch (std::bad_alloc &)
916 {
917 return E_OUTOFMEMORY;
918 }
919 return S_OK;
920}
921
922
923//////////////////////////////////////////////////////////////////////////////////////////////////////
924/*
925*
926*
927* Implementation UnattendedDebianInstaller functions
928*
929*/
930//////////////////////////////////////////////////////////////////////////////////////////////////////
931
932/**
933 * Helper for checking if a file exists.
934 * @todo promote to IPRT?
935 */
936static bool hlpVfsFileExists(RTVFS hVfs, const char *pszPath)
937{
938 RTFSOBJINFO ObjInfo;
939 int vrc = RTVfsQueryPathInfo(hVfs, pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
940 return RT_SUCCESS(vrc) && RTFS_IS_FILE(ObjInfo.Attr.fMode);
941}
942
943HRESULT UnattendedDebianInstaller::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
944 RTVFS hVfsOrgIso, bool fOverwrite)
945{
946 /*
947 * The txt.cfg file used to be called isolinux.txt (ubuntu 4.10
948 * and possible others).
949 */
950 /** @todo Ubuntu 4.10 does not work, as we generate too long command lines
951 * and the kernel crashes immediately. */
952 const char *pszIsoLinuxTxtCfg = "/isolinux/txt.cfg";
953 if ( !hlpVfsFileExists(hVfsOrgIso, pszIsoLinuxTxtCfg)
954 && hlpVfsFileExists(hVfsOrgIso, "/isolinux/isolinux.txt"))
955 pszIsoLinuxTxtCfg = "/isolinux/isolinux.txt";
956
957 /*
958 * VISO bits and filenames.
959 */
960 RTCString strIsoLinuxCfg;
961 RTCString strTxtCfg;
962 try
963 {
964 /* Remaster ISO. */
965 rVecArgs.append() = "--no-file-mode";
966 rVecArgs.append() = "--no-dir-mode";
967
968 rVecArgs.append() = "--import-iso";
969 rVecArgs.append(mpParent->i_getIsoPath());
970
971 rVecArgs.append() = "--file-mode=0444";
972 rVecArgs.append() = "--dir-mode=0555";
973
974 /* Remove the two isolinux configure files we'll be replacing. */
975 rVecArgs.append() = "isolinux/isolinux.cfg=:must-remove:";
976 rVecArgs.append().assign(&pszIsoLinuxTxtCfg[1]).append("=:must-remove:");
977
978 /* Add the replacement files. */
979 strIsoLinuxCfg = mpParent->i_getAuxiliaryBasePath();
980 strIsoLinuxCfg.append("isolinux-isolinux.cfg");
981 rVecArgs.append().append("isolinux/isolinux.cfg=").append(strIsoLinuxCfg);
982
983 strTxtCfg = mpParent->i_getAuxiliaryBasePath();
984 strTxtCfg.append("isolinux-txt.cfg");
985 rVecArgs.append().assign(&pszIsoLinuxTxtCfg[1]).append("=").append(strTxtCfg);
986 }
987 catch (std::bad_alloc &)
988 {
989 return E_OUTOFMEMORY;
990 }
991
992 /*
993 * Edit the isolinux.cfg file.
994 */
995 {
996 GeneralTextScript Editor(mpParent);
997 HRESULT hrc = loadAndParseFileFromIso(hVfsOrgIso, "/isolinux/isolinux.cfg", &Editor);
998 if (SUCCEEDED(hrc))
999 hrc = editIsoLinuxCfg(&Editor);
1000 if (SUCCEEDED(hrc))
1001 {
1002 hrc = Editor.save(strIsoLinuxCfg, fOverwrite);
1003 if (SUCCEEDED(hrc))
1004 {
1005 try
1006 {
1007 rVecFiles.append(strIsoLinuxCfg);
1008 }
1009 catch (std::bad_alloc &)
1010 {
1011 RTFileDelete(strIsoLinuxCfg.c_str());
1012 hrc = E_OUTOFMEMORY;
1013 }
1014 }
1015 }
1016 if (FAILED(hrc))
1017 return hrc;
1018 }
1019
1020 /*
1021 * Edit the txt.cfg file.
1022 */
1023 {
1024 GeneralTextScript Editor(mpParent);
1025 HRESULT hrc = loadAndParseFileFromIso(hVfsOrgIso, pszIsoLinuxTxtCfg, &Editor);
1026 if (SUCCEEDED(hrc))
1027 hrc = editDebianTxtCfg(&Editor);
1028 if (SUCCEEDED(hrc))
1029 {
1030 hrc = Editor.save(strTxtCfg, fOverwrite);
1031 if (SUCCEEDED(hrc))
1032 {
1033 try
1034 {
1035 rVecFiles.append(strTxtCfg);
1036 }
1037 catch (std::bad_alloc &)
1038 {
1039 RTFileDelete(strTxtCfg.c_str());
1040 hrc = E_OUTOFMEMORY;
1041 }
1042 }
1043 }
1044 if (FAILED(hrc))
1045 return hrc;
1046 }
1047
1048 /*
1049 * Call parent to add the preseed file from mAlg.
1050 */
1051 return UnattendedLinuxInstaller::addFilesToAuxVisoVectors(rVecArgs, rVecFiles, hVfsOrgIso, fOverwrite);
1052}
1053
1054HRESULT UnattendedDebianInstaller::editDebianTxtCfg(GeneralTextScript *pEditor)
1055{
1056 try
1057 {
1058 /** @todo r=bird: Add some comments saying wtf you're actually up to here.
1059 * Repeating what's clear from function calls and boasting the
1060 * inteligence of the code isn't helpful. */
1061 //find all lines with "label" inside
1062 std::vector<size_t> vecLineNumbers = pEditor->findTemplate("label", RTCString::CaseInsensitive);
1063 for (size_t i = 0; i < vecLineNumbers.size(); ++i)
1064 {
1065 RTCString const &rContent = pEditor->getContentOfLine(vecLineNumbers[i]);
1066
1067 // ASSUME: suppose general string looks like "label install", two words separated by " ".
1068 RTCList<RTCString> vecPartsOfcontent = rContent.split(" ");
1069 if (vecPartsOfcontent.size() > 1 && vecPartsOfcontent[1].contains("install")) /** @todo r=bird: case insensitive? */
1070 {
1071 std::vector<size_t> vecDefaultLineNumbers = pEditor->findTemplate("default", RTCString::CaseInsensitive);
1072 //handle the lines more intelligently
1073 for (size_t j = 0; j < vecDefaultLineNumbers.size(); ++j)
1074 {
1075 Utf8Str strNewContent("default ");
1076 strNewContent.append(vecPartsOfcontent[1]);
1077 HRESULT hrc = pEditor->setContentOfLine(vecDefaultLineNumbers[j], strNewContent);
1078 if (FAILED(hrc))
1079 return hrc;
1080 }
1081 }
1082 }
1083 }
1084 catch (std::bad_alloc &)
1085 {
1086 return E_OUTOFMEMORY;
1087 }
1088 return UnattendedLinuxInstaller::editIsoLinuxCfg(pEditor);
1089}
1090
1091
1092//////////////////////////////////////////////////////////////////////////////////////////////////////
1093/*
1094*
1095*
1096* Implementation UnattendedRhel6Installer functions
1097*
1098*/
1099//////////////////////////////////////////////////////////////////////////////////////////////////////
1100HRESULT UnattendedRhel6Installer::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
1101 RTVFS hVfsOrgIso, bool fOverwrite)
1102{
1103 Utf8Str strIsoLinuxCfg;
1104 try
1105 {
1106#if 1
1107 /* Remaster ISO. */
1108 rVecArgs.append() = "--no-file-mode";
1109 rVecArgs.append() = "--no-dir-mode";
1110
1111 rVecArgs.append() = "--import-iso";
1112 rVecArgs.append(mpParent->i_getIsoPath());
1113
1114 rVecArgs.append() = "--file-mode=0444";
1115 rVecArgs.append() = "--dir-mode=0555";
1116
1117 /* We replace isolinux.cfg with our edited version (see further down). */
1118 rVecArgs.append() = "isolinux/isolinux.cfg=:must-remove:";
1119 strIsoLinuxCfg = mpParent->i_getAuxiliaryBasePath();
1120 strIsoLinuxCfg.append("isolinux-isolinux.cfg");
1121 rVecArgs.append().append("isolinux/isolinux.cfg=").append(strIsoLinuxCfg);
1122
1123#else
1124 /** @todo Maybe we should just remaster the ISO for redhat derivatives too?
1125 * One less CDROM to mount. */
1126 /* Name the ISO. */
1127 rVecArgs.append() = "--volume-id=VBox Unattended Boot";
1128
1129 /* Copy the isolinux directory from the original install ISO. */
1130 rVecArgs.append().append("--push-iso=").append(mpParent->i_getIsoPath());
1131 rVecArgs.append() = "/isolinux=/isolinux";
1132 rVecArgs.append() = "--pop";
1133
1134 /* We replace isolinux.cfg with our edited version (see further down). */
1135 rVecArgs.append() = "/isolinux/isolinux.cfg=:must-remove:";
1136
1137 strIsoLinuxCfg = mpParent->i_getAuxiliaryBasePath();
1138 strIsoLinuxCfg.append("isolinux-isolinux.cfg");
1139 rVecArgs.append().append("/isolinux/isolinux.cfg=").append(strIsoLinuxCfg);
1140
1141 /* Configure booting /isolinux/isolinux.bin. */
1142 rVecArgs.append() = "--eltorito-boot";
1143 rVecArgs.append() = "/isolinux/isolinux.bin";
1144 rVecArgs.append() = "--no-emulation-boot";
1145 rVecArgs.append() = "--boot-info-table";
1146 rVecArgs.append() = "--boot-load-seg=0x07c0";
1147 rVecArgs.append() = "--boot-load-size=4";
1148
1149 /* Make the boot catalog visible in the file system. */
1150 rVecArgs.append() = "--boot-catalog=/isolinux/vboxboot.cat";
1151#endif
1152 }
1153 catch (std::bad_alloc &)
1154 {
1155 return E_OUTOFMEMORY;
1156 }
1157
1158 /*
1159 * Edit isolinux.cfg and save it.
1160 */
1161 {
1162 GeneralTextScript Editor(mpParent);
1163 HRESULT hrc = loadAndParseFileFromIso(hVfsOrgIso, "/isolinux/isolinux.cfg", &Editor);
1164 if (SUCCEEDED(hrc))
1165 hrc = editIsoLinuxCfg(&Editor);
1166 if (SUCCEEDED(hrc))
1167 {
1168 hrc = Editor.save(strIsoLinuxCfg, fOverwrite);
1169 if (SUCCEEDED(hrc))
1170 {
1171 try
1172 {
1173 rVecFiles.append(strIsoLinuxCfg);
1174 }
1175 catch (std::bad_alloc &)
1176 {
1177 RTFileDelete(strIsoLinuxCfg.c_str());
1178 hrc = E_OUTOFMEMORY;
1179 }
1180 }
1181 }
1182 if (FAILED(hrc))
1183 return hrc;
1184 }
1185
1186 /*
1187 * Call parent to add the ks.cfg file from mAlg.
1188 */
1189 return UnattendedLinuxInstaller::addFilesToAuxVisoVectors(rVecArgs, rVecFiles, hVfsOrgIso, fOverwrite);
1190}
1191
1192
1193//////////////////////////////////////////////////////////////////////////////////////////////////////
1194/*
1195*
1196*
1197* Implementation UnattendedSuseInstaller functions
1198*
1199*/
1200//////////////////////////////////////////////////////////////////////////////////////////////////////
1201#if 0 /* doesn't work, so convert later */
1202/*
1203 *
1204 * UnattendedSuseInstaller protected methods
1205 *
1206*/
1207HRESULT UnattendedSuseInstaller::setUserData()
1208{
1209 HRESULT rc = S_OK;
1210 //here base class function must be called first
1211 //because user home directory is set after user name
1212 rc = UnattendedInstaller::setUserData();
1213
1214 rc = mAlg->setField(USERHOMEDIR_ID, "");
1215 if (FAILED(rc))
1216 return rc;
1217
1218 return rc;
1219}
1220
1221/*
1222 *
1223 * UnattendedSuseInstaller private methods
1224 *
1225*/
1226
1227HRESULT UnattendedSuseInstaller::iv_initialPhase()
1228{
1229 Assert(isAuxiliaryIsoNeeded());
1230 if (mParent->i_isGuestOs64Bit())
1231 mFilesAndDirsToExtractFromIso.append("boot/x86_64/loader/ ");
1232 else
1233 mFilesAndDirsToExtractFromIso.append("boot/i386/loader/ ");
1234 return extractOriginalIso(mFilesAndDirsToExtractFromIso);
1235}
1236
1237
1238HRESULT UnattendedSuseInstaller::setupScriptOnAuxiliaryCD(const Utf8Str &path)
1239{
1240 HRESULT rc = S_OK;
1241
1242 GeneralTextScript isoSuseCfgScript(mpParent);
1243 rc = isoSuseCfgScript.read(path);
1244 rc = isoSuseCfgScript.parse();
1245 //fix linux core bootable parameters: add path to the preseed script
1246
1247 std::vector<size_t> listOfLines = isoSuseCfgScript.findTemplate("append");
1248 for(unsigned int i=0; i<listOfLines.size(); ++i)
1249 {
1250 isoSuseCfgScript.appendToLine(listOfLines.at(i),
1251 " auto=true priority=critical autoyast=default instmode=cd quiet splash noprompt noshell --");
1252 }
1253
1254 //find all lines with "label" inside
1255 listOfLines = isoSuseCfgScript.findTemplate("label");
1256 for(unsigned int i=0; i<listOfLines.size(); ++i)
1257 {
1258 Utf8Str content = isoSuseCfgScript.getContentOfLine(listOfLines.at(i));
1259
1260 //suppose general string looks like "label linux", two words separated by " ".
1261 RTCList<RTCString> partsOfcontent = content.split(" ");
1262
1263 if (partsOfcontent.at(1).contains("linux"))
1264 {
1265 std::vector<size_t> listOfDefault = isoSuseCfgScript.findTemplate("default");
1266 //handle the lines more intelligently
1267 for(unsigned int j=0; j<listOfDefault.size(); ++j)
1268 {
1269 Utf8Str newContent("default ");
1270 newContent.append(partsOfcontent.at(1));
1271 isoSuseCfgScript.setContentOfLine(listOfDefault.at(j), newContent);
1272 }
1273 }
1274 }
1275
1276 rc = isoSuseCfgScript.save(path, true);
1277
1278 LogRelFunc(("UnattendedSuseInstaller::setupScriptsOnAuxiliaryCD(): The file %s has been changed\n", path.c_str()));
1279
1280 return rc;
1281}
1282#endif
1283
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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