VirtualBox

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

Last change on this file since 68162 was 68162, checked in by vboxsync, 8 years ago

Main: export Unattended* source files.

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

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