VirtualBox

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

Last change on this file since 85672 was 85275, checked in by vboxsync, 4 years ago

Main/UnattendedInstaller.cpp: Return code mixup (harmless). bugref:9790

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

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