VirtualBox

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

Last change on this file since 71963 was 71018, checked in by vboxsync, 7 years ago

Main,Installer: Made unattended installation work for rhel3 and friends.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.6 KB
Line 
1/* $Id: UnattendedInstaller.cpp 71018 2018-02-14 18:42:52Z vboxsync $ */
2/** @file
3 * UnattendedInstaller class and it's descendants implementation
4 */
5
6/*
7 * Copyright (C) 2006-2017 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 vrc;
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 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 additions ISO, add its content to a /vboxadditions 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
915HRESULT UnattendedDebianInstaller::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
916 RTVFS hVfsOrgIso, bool fOverwrite)
917{
918 /*
919 * VISO bits and filenames.
920 */
921 RTCString strIsoLinuxCfg;
922 RTCString strTxtCfg;
923 try
924 {
925 /* Remaster ISO. */
926 rVecArgs.append() = "--no-file-mode";
927 rVecArgs.append() = "--no-dir-mode";
928
929 rVecArgs.append() = "--import-iso";
930 rVecArgs.append(mpParent->i_getIsoPath());
931
932 rVecArgs.append() = "--file-mode=0444";
933 rVecArgs.append() = "--dir-mode=0555";
934
935 /* Remove the two isolinux configure files we'll be replacing. */
936 rVecArgs.append() = "isolinux/isolinux.cfg=:must-remove:";
937 rVecArgs.append() = "isolinux/txt.cfg=:must-remove:";
938
939 /* Add the replacement files. */
940 strIsoLinuxCfg = mpParent->i_getAuxiliaryBasePath();
941 strIsoLinuxCfg.append("isolinux-isolinux.cfg");
942 rVecArgs.append().append("isolinux/isolinux.cfg=").append(strIsoLinuxCfg);
943
944 strTxtCfg = mpParent->i_getAuxiliaryBasePath();
945 strTxtCfg.append("isolinux-txt.cfg");
946 rVecArgs.append().append("isolinux/txt.cfg=").append(strTxtCfg);
947 }
948 catch (std::bad_alloc)
949 {
950 return E_OUTOFMEMORY;
951 }
952
953 /*
954 * Edit the isolinux.cfg file.
955 */
956 {
957 GeneralTextScript Editor(mpParent);
958 HRESULT hrc = loadAndParseFileFromIso(hVfsOrgIso, "/isolinux/isolinux.cfg", &Editor);
959 if (SUCCEEDED(hrc))
960 hrc = editIsoLinuxCfg(&Editor);
961 if (SUCCEEDED(hrc))
962 {
963 hrc = Editor.save(strIsoLinuxCfg, fOverwrite);
964 if (SUCCEEDED(hrc))
965 {
966 try
967 {
968 rVecFiles.append(strIsoLinuxCfg);
969 }
970 catch (std::bad_alloc)
971 {
972 RTFileDelete(strIsoLinuxCfg.c_str());
973 hrc = E_OUTOFMEMORY;
974 }
975 }
976 }
977 if (FAILED(hrc))
978 return hrc;
979 }
980
981 /*
982 * Edit the txt.cfg file.
983 */
984 {
985 GeneralTextScript Editor(mpParent);
986 HRESULT hrc = loadAndParseFileFromIso(hVfsOrgIso, "/isolinux/txt.cfg", &Editor);
987 if (SUCCEEDED(hrc))
988 hrc = editDebianTxtCfg(&Editor);
989 if (SUCCEEDED(hrc))
990 {
991 hrc = Editor.save(strTxtCfg, fOverwrite);
992 if (SUCCEEDED(hrc))
993 {
994 try
995 {
996 rVecFiles.append(strTxtCfg);
997 }
998 catch (std::bad_alloc)
999 {
1000 RTFileDelete(strTxtCfg.c_str());
1001 hrc = E_OUTOFMEMORY;
1002 }
1003 }
1004 }
1005 if (FAILED(hrc))
1006 return hrc;
1007 }
1008
1009 /*
1010 * Call parent to add the preseed file from mAlg.
1011 */
1012 return UnattendedLinuxInstaller::addFilesToAuxVisoVectors(rVecArgs, rVecFiles, hVfsOrgIso, fOverwrite);
1013}
1014
1015HRESULT UnattendedDebianInstaller::editDebianTxtCfg(GeneralTextScript *pEditor)
1016{
1017 try
1018 {
1019 /** @todo r=bird: Add some comments saying wtf you're actually up to here.
1020 * Repeating what's clear from function calls and boasting the
1021 * inteligence of the code isn't helpful. */
1022 //find all lines with "label" inside
1023 std::vector<size_t> vecLineNumbers = pEditor->findTemplate("label", RTCString::CaseInsensitive);
1024 for (size_t i = 0; i < vecLineNumbers.size(); ++i)
1025 {
1026 RTCString const &rContent = pEditor->getContentOfLine(vecLineNumbers[i]);
1027
1028 // ASSUME: suppose general string looks like "label install", two words separated by " ".
1029 RTCList<RTCString> vecPartsOfcontent = rContent.split(" ");
1030 if (vecPartsOfcontent.size() > 1 && vecPartsOfcontent[1].contains("install")) /** @todo r=bird: case insensitive? */
1031 {
1032 std::vector<size_t> vecDefaultLineNumbers = pEditor->findTemplate("default", RTCString::CaseInsensitive);
1033 //handle the lines more intelligently
1034 for (size_t j = 0; j < vecDefaultLineNumbers.size(); ++j)
1035 {
1036 Utf8Str strNewContent("default ");
1037 strNewContent.append(vecPartsOfcontent[1]);
1038 HRESULT hrc = pEditor->setContentOfLine(vecDefaultLineNumbers[j], strNewContent);
1039 if (FAILED(hrc))
1040 return hrc;
1041 }
1042 }
1043 }
1044 }
1045 catch (std::bad_alloc)
1046 {
1047 return E_OUTOFMEMORY;
1048 }
1049 return UnattendedLinuxInstaller::editIsoLinuxCfg(pEditor);
1050}
1051
1052
1053//////////////////////////////////////////////////////////////////////////////////////////////////////
1054/*
1055*
1056*
1057* Implementation UnattendedRhel6And7Installer functions
1058*
1059*/
1060//////////////////////////////////////////////////////////////////////////////////////////////////////
1061HRESULT UnattendedRhel6And7Installer::addFilesToAuxVisoVectors(RTCList<RTCString> &rVecArgs, RTCList<RTCString> &rVecFiles,
1062 RTVFS hVfsOrgIso, bool fOverwrite)
1063{
1064 Utf8Str strIsoLinuxCfg;
1065 try
1066 {
1067#if 1
1068 /* Remaster ISO. */
1069 rVecArgs.append() = "--no-file-mode";
1070 rVecArgs.append() = "--no-dir-mode";
1071
1072 rVecArgs.append() = "--import-iso";
1073 rVecArgs.append(mpParent->i_getIsoPath());
1074
1075 rVecArgs.append() = "--file-mode=0444";
1076 rVecArgs.append() = "--dir-mode=0555";
1077
1078 /* We replace isolinux.cfg with our edited version (see further down). */
1079 rVecArgs.append() = "isolinux/isolinux.cfg=:must-remove:";
1080 strIsoLinuxCfg = mpParent->i_getAuxiliaryBasePath();
1081 strIsoLinuxCfg.append("isolinux-isolinux.cfg");
1082 rVecArgs.append().append("isolinux/isolinux.cfg=").append(strIsoLinuxCfg);
1083
1084#else
1085 /** @todo Maybe we should just remaster the ISO for redhat derivatives too?
1086 * One less CDROM to mount. */
1087 /* Name the ISO. */
1088 rVecArgs.append() = "--volume-id=VBox Unattended Boot";
1089
1090 /* Copy the isolinux directory from the original install ISO. */
1091 rVecArgs.append().append("--push-iso=").append(mpParent->i_getIsoPath());
1092 rVecArgs.append() = "/isolinux=/isolinux";
1093 rVecArgs.append() = "--pop";
1094
1095 /* We replace isolinux.cfg with our edited version (see further down). */
1096 rVecArgs.append() = "/isolinux/isolinux.cfg=:must-remove:";
1097
1098 strIsoLinuxCfg = mpParent->i_getAuxiliaryBasePath();
1099 strIsoLinuxCfg.append("isolinux-isolinux.cfg");
1100 rVecArgs.append().append("/isolinux/isolinux.cfg=").append(strIsoLinuxCfg);
1101
1102 /* Configure booting /isolinux/isolinux.bin. */
1103 rVecArgs.append() = "--eltorito-boot";
1104 rVecArgs.append() = "/isolinux/isolinux.bin";
1105 rVecArgs.append() = "--no-emulation-boot";
1106 rVecArgs.append() = "--boot-info-table";
1107 rVecArgs.append() = "--boot-load-seg=0x07c0";
1108 rVecArgs.append() = "--boot-load-size=4";
1109
1110 /* Make the boot catalog visible in the file system. */
1111 rVecArgs.append() = "--boot-catalog=/isolinux/vboxboot.cat";
1112#endif
1113 }
1114 catch (std::bad_alloc)
1115 {
1116 return E_OUTOFMEMORY;
1117 }
1118
1119 /*
1120 * Edit isolinux.cfg and save it.
1121 */
1122 {
1123 GeneralTextScript Editor(mpParent);
1124 HRESULT hrc = loadAndParseFileFromIso(hVfsOrgIso, "/isolinux/isolinux.cfg", &Editor);
1125 if (SUCCEEDED(hrc))
1126 hrc = editIsoLinuxCfg(&Editor);
1127 if (SUCCEEDED(hrc))
1128 {
1129 hrc = Editor.save(strIsoLinuxCfg, fOverwrite);
1130 if (SUCCEEDED(hrc))
1131 {
1132 try
1133 {
1134 rVecFiles.append(strIsoLinuxCfg);
1135 }
1136 catch (std::bad_alloc)
1137 {
1138 RTFileDelete(strIsoLinuxCfg.c_str());
1139 hrc = E_OUTOFMEMORY;
1140 }
1141 }
1142 }
1143 if (FAILED(hrc))
1144 return hrc;
1145 }
1146
1147 /*
1148 * Call parent to add the ks.cfg file from mAlg.
1149 */
1150 return UnattendedLinuxInstaller::addFilesToAuxVisoVectors(rVecArgs, rVecFiles, hVfsOrgIso, fOverwrite);
1151}
1152
1153
1154//////////////////////////////////////////////////////////////////////////////////////////////////////
1155/*
1156*
1157*
1158* Implementation UnattendedSuseInstaller functions
1159*
1160*/
1161//////////////////////////////////////////////////////////////////////////////////////////////////////
1162#if 0 /* doesn't work, so convert later */
1163/*
1164 *
1165 * UnattendedSuseInstaller protected methods
1166 *
1167*/
1168HRESULT UnattendedSuseInstaller::setUserData()
1169{
1170 HRESULT rc = S_OK;
1171 //here base class function must be called first
1172 //because user home directory is set after user name
1173 rc = UnattendedInstaller::setUserData();
1174
1175 rc = mAlg->setField(USERHOMEDIR_ID, "");
1176 if (FAILED(rc))
1177 return rc;
1178
1179 return rc;
1180}
1181
1182/*
1183 *
1184 * UnattendedSuseInstaller private methods
1185 *
1186*/
1187
1188HRESULT UnattendedSuseInstaller::iv_initialPhase()
1189{
1190 Assert(isAuxiliaryIsoNeeded());
1191 if (mParent->i_isGuestOs64Bit())
1192 mFilesAndDirsToExtractFromIso.append("boot/x86_64/loader/ ");
1193 else
1194 mFilesAndDirsToExtractFromIso.append("boot/i386/loader/ ");
1195 return extractOriginalIso(mFilesAndDirsToExtractFromIso);
1196}
1197
1198
1199HRESULT UnattendedSuseInstaller::setupScriptOnAuxiliaryCD(const Utf8Str &path)
1200{
1201 HRESULT rc = S_OK;
1202
1203 GeneralTextScript isoSuseCfgScript(mpParent);
1204 rc = isoSuseCfgScript.read(path);
1205 rc = isoSuseCfgScript.parse();
1206 //fix linux core bootable parameters: add path to the preseed script
1207
1208 std::vector<size_t> listOfLines = isoSuseCfgScript.findTemplate("append");
1209 for(unsigned int i=0; i<listOfLines.size(); ++i)
1210 {
1211 isoSuseCfgScript.appendToLine(listOfLines.at(i),
1212 " auto=true priority=critical autoyast=default instmode=cd quiet splash noprompt noshell --");
1213 }
1214
1215 //find all lines with "label" inside
1216 listOfLines = isoSuseCfgScript.findTemplate("label");
1217 for(unsigned int i=0; i<listOfLines.size(); ++i)
1218 {
1219 Utf8Str content = isoSuseCfgScript.getContentOfLine(listOfLines.at(i));
1220
1221 //suppose general string looks like "label linux", two words separated by " ".
1222 RTCList<RTCString> partsOfcontent = content.split(" ");
1223
1224 if (partsOfcontent.at(1).contains("linux"))
1225 {
1226 std::vector<size_t> listOfDefault = isoSuseCfgScript.findTemplate("default");
1227 //handle the lines more intelligently
1228 for(unsigned int j=0; j<listOfDefault.size(); ++j)
1229 {
1230 Utf8Str newContent("default ");
1231 newContent.append(partsOfcontent.at(1));
1232 isoSuseCfgScript.setContentOfLine(listOfDefault.at(j), newContent);
1233 }
1234 }
1235 }
1236
1237 rc = isoSuseCfgScript.save(path, true);
1238
1239 LogRelFunc(("UnattendedSuseInstaller::setupScriptsOnAuxiliaryCD(): The file %s has been changed\n", path.c_str()));
1240
1241 return rc;
1242}
1243#endif
1244
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