VirtualBox

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

Last change on this file since 90828 was 90828, checked in by vboxsync, 3 years ago

Main: bugref:1909: Added API localization

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