VirtualBox

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

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

Main,Installer: Made unattended installation of rhel5 and friends work. Fixed TXS bug in post-install script.

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