VirtualBox

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

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

Main: Squeeze the validation kit and additions onto the aux image when installing windows vista+. Implemented setting up vboxtxs.

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