Changeset 81425 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Oct 21, 2019 6:19:39 PM (5 years ago)
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/BIOSSettingsImpl.cpp
r81299 r81425 153 153 m->bd.attachCopy(that->m->bd); 154 154 155 // Intentionally "forget" the NVRAM file since it must be unique and set 156 // to the correct value before the copy of the settings makes sense. 157 m->bd->strNVRAMPath.setNull(); 158 155 159 autoInitSpan.setSucceeded(); 156 160 … … 373 377 374 378 m->bd.backup(); 375 376 379 m->bd->fIOAPICEnabled = RT_BOOL(aIOAPICEnabled); 380 377 381 alock.release(); 378 382 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking … … 401 405 402 406 m->bd.backup(); 403 404 407 m->bd->apicMode = aAPICMode; 408 405 409 alock.release(); 406 410 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS); // mParent is const, needs no locking … … 591 595 /* this will back up current data */ 592 596 m->bd.assignCopy(aThat->m->bd); 597 598 // Intentionally "forget" the NVRAM file since it must be unique and set 599 // to the correct value before the copy of the settings makes sense. 600 m->bd->strNVRAMPath.setNull(); 601 593 602 } 594 603 … … 608 617 } 609 618 619 Utf8Str BIOSSettings::i_getNonVolatileStorageFile() 620 { 621 AutoCaller autoCaller(this); 622 AssertComRCReturn(autoCaller.rc(), Utf8Str::Empty); 623 624 Utf8Str strTmp; 625 BIOSSettings::getNonVolatileStorageFile(strTmp); 626 return strTmp; 627 } 628 610 629 void BIOSSettings::i_updateNonVolatileStorageFile(const Utf8Str &aNonVolatileStorageFile) 611 630 { -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r81422 r81425 5025 5025 if (!mData->mAccessible) 5026 5026 { 5027 // inaccessible ma schines can only be unregistered; uninitialize ourselves5027 // inaccessible machines can only be unregistered; uninitialize ourselves 5028 5028 // here because currently there may be no unregistered that are inaccessible 5029 5029 // (this state combination is not supported). Note releasing the caller and … … 5041 5041 5042 5042 HRESULT rc = S_OK; 5043 5044 /// @todo r=klaus this is stupid... why is the saved state always deleted? 5045 // discard saved state 5046 if (mData->mMachineState == MachineState_Saved) 5047 { 5048 // add the saved state file to the list of files the caller should delete 5049 Assert(!mSSData->strStateFilePath.isEmpty()); 5043 mData->llFilesToDelete.clear(); 5044 5045 if (!mSSData->strStateFilePath.isEmpty()) 5050 5046 mData->llFilesToDelete.push_back(mSSData->strStateFilePath); 5051 5047 5052 mSSData->strStateFilePath.setNull(); 5053 5054 // unconditionally set the machine state to powered off, we now 5055 // know no session has locked the machine 5056 mData->mMachineState = MachineState_PoweredOff; 5057 } 5058 5059 size_t cSnapshots = 0; 5060 if (mData->mFirstSnapshot) 5061 cSnapshots = mData->mFirstSnapshot->i_getAllChildrenCount() + 1; 5062 if (cSnapshots && aCleanupMode == CleanupMode_UnregisterOnly) 5063 // fail now before we start detaching media 5064 return setError(VBOX_E_INVALID_OBJECT_STATE, 5065 tr("Cannot unregister the machine '%s' because it has %d snapshots"), 5066 mUserData->s.strName.c_str(), cSnapshots); 5048 Utf8Str strNVRAMFile = mBIOSSettings->i_getNonVolatileStorageFile(); 5049 if (!strNVRAMFile.isEmpty() && RTFileExists(strNVRAMFile.c_str())) 5050 mData->llFilesToDelete.push_back(strNVRAMFile); 5067 5051 5068 5052 // This list collects the medium objects from all medium attachments … … 5082 5066 { 5083 5067 // we have media attachments: detach them all and add the Medium objects to our list 5084 if (aCleanupMode != CleanupMode_UnregisterOnly) 5085 i_detachAllMedia(alock, NULL /* pSnapshot */, aCleanupMode, llMedia); 5086 else 5087 return setError(VBOX_E_INVALID_OBJECT_STATE, 5088 tr("Cannot unregister the machine '%s' because it has %d media attachments"), 5089 mUserData->s.strName.c_str(), mMediumAttachments->size()); 5090 } 5091 5092 if (cSnapshots) 5068 i_detachAllMedia(alock, NULL /* pSnapshot */, aCleanupMode, llMedia); 5069 } 5070 5071 if (mData->mFirstSnapshot) 5093 5072 { 5094 5073 // add the media from the medium attachments of the snapshots to llMedia … … 5101 5080 mData->mMachineState = MachineState_DeletingSnapshot; 5102 5081 5103 // make a copy of the first snapshot so the refcount does not drop to 05104 // in beginDeletingSnapshot, which sets pFirstSnapshot to 0 (that hangs5105 // because ofthe AutoCaller voodoo)5082 // make a copy of the first snapshot reference so the refcount does not 5083 // drop to 0 in beginDeletingSnapshot, which sets pFirstSnapshot to 0 5084 // (would hang due to the AutoCaller voodoo) 5106 5085 ComObjPtr<Snapshot> pFirstSnapshot = mData->mFirstSnapshot; 5107 5086 … … 5125 5104 // machine lock no longer needed 5126 5105 alock.release(); 5106 5107 /* Make sure that the settings of the current VM are not saved, because 5108 * they are rather crippled at this point to meet the cleanup expectations 5109 * and there's no point destroying the VM config on disk just because. */ 5110 mParent->i_unmarkRegistryModified(id); 5127 5111 5128 5112 // return media to caller … … 5365 5349 5366 5350 // collect files to delete 5367 StringsList llFilesToDelete(mData->llFilesToDelete); // saved states pushed here by Unregister() 5351 StringsList llFilesToDelete(mData->llFilesToDelete); // saved states and NVRAM files pushed here by Unregister() 5352 // machine config file 5368 5353 if (mData->pMachineConfigFile->fileExists()) 5369 5354 llFilesToDelete.push_back(mData->m_strConfigFileFull); 5355 // backup of machine config file 5356 Utf8Str strTmp(mData->m_strConfigFileFull); 5357 strTmp.append("-prev"); 5358 if (RTFileExists(strTmp.c_str())) 5359 llFilesToDelete.push_back(strTmp); 5370 5360 5371 5361 RTCList<ComPtr<IMedium> > llMediums; … … 7362 7352 /** 7363 7353 * Returns the default NVRAM filename based on the location of the VM config. 7364 * This intentionally works differently than the saved state file naming since 7365 * it is part of the current state. Taking a snapshot will use a similar naming 7366 * as for saved state, because these are actually read-only, retaining a 7367 * a specific state just like saved state. Note that this is a relative path. 7354 * Note that this is a relative path. 7368 7355 */ 7369 7370 7356 Utf8Str Machine::i_getDefaultNVRAMFilename() 7371 7357 { … … 7375 7361 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 7376 7362 7377 if (mHWData->mFirmwareType == FirmwareType_BIOS) 7363 if ( mHWData->mFirmwareType == FirmwareType_BIOS 7364 || i_isSnapshotMachine()) 7378 7365 return Utf8Str::Empty; 7379 7366 … … 7386 7373 } 7387 7374 7375 /** 7376 * Returns the NVRAM filename for a new snapshot. This intentionally works 7377 * similarly to the saved state file naming. Note that this is usually 7378 * a relative path, unless the snapshot folder is absolute. 7379 */ 7380 Utf8Str Machine::i_getSnapshotNVRAMFilename() 7381 { 7382 AutoCaller autoCaller(this); 7383 AssertComRCReturn(autoCaller.rc(), Utf8Str::Empty); 7384 7385 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 7386 7387 if (mHWData->mFirmwareType == FirmwareType_BIOS) 7388 return Utf8Str::Empty; 7389 7390 RTTIMESPEC ts; 7391 RTTimeNow(&ts); 7392 RTTIME time; 7393 RTTimeExplode(&time, &ts); 7394 7395 Utf8Str strNVRAMFilePath = mUserData->s.strSnapshotFolder; 7396 strNVRAMFilePath += RTPATH_DELIMITER; 7397 strNVRAMFilePath += Utf8StrFmt("%04d-%02u-%02uT%02u-%02u-%02u-%09uZ.nvram", 7398 time.i32Year, time.u8Month, time.u8MonthDay, 7399 time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond); 7400 7401 return strNVRAMFilePath; 7402 } 7388 7403 7389 7404 /** … … 9727 9742 Utf8Str configFile, newConfigFile; 9728 9743 Utf8Str configFilePrev, newConfigFilePrev; 9744 Utf8Str NVRAMFile, newNVRAMFile; 9729 9745 Utf8Str configDir, newConfigDir; 9730 9746 … … 9836 9852 newConfigFilePrev += "-prev"; 9837 9853 RTFileRename(configFilePrev.c_str(), newConfigFilePrev.c_str(), 0); 9854 NVRAMFile = mBIOSSettings->i_getNonVolatileStorageFile(); 9855 if (NVRAMFile.isNotEmpty()) 9856 { 9857 // in the NVRAM file path, replace the old directory with the new directory 9858 if (RTPathStartsWith(NVRAMFile.c_str(), configDir.c_str())) 9859 { 9860 Utf8Str strNVRAMFile = NVRAMFile.c_str() + configDir.length(); 9861 NVRAMFile = newConfigDir + strNVRAMFile; 9862 } 9863 newNVRAMFile = newConfigFile; 9864 newNVRAMFile.stripSuffix(); 9865 newNVRAMFile += ".nvram"; 9866 RTFileRename(NVRAMFile.c_str(), newNVRAMFile.c_str(), 0); 9867 } 9838 9868 } 9839 9869 } … … 9861 9891 mSSData->strStateFilePath = newConfigDir + strStateFileName; 9862 9892 } 9863 9864 // and do the same thing for the saved state file paths of all the online snapshots 9893 if (newNVRAMFile.isNotEmpty()) 9894 mBIOSSettings->i_updateNonVolatileStorageFile(newNVRAMFile); 9895 9896 // and do the same thing for the saved state file paths of all the online snapshots and NVRAM files of all snapshots 9865 9897 if (mData->mFirstSnapshot) 9898 { 9866 9899 mData->mFirstSnapshot->i_updateSavedStatePaths(configDir.c_str(), 9867 9900 newConfigDir.c_str()); 9901 mData->mFirstSnapshot->i_updateNVRAMPaths(configDir.c_str(), 9902 newConfigDir.c_str()); 9903 } 9868 9904 } 9869 9905 while (0); … … 9876 9912 RTFileRename(newConfigFilePrev.c_str(), configFilePrev.c_str(), 0); 9877 9913 RTFileRename(newConfigFile.c_str(), configFile.c_str(), 0); 9914 if (NVRAMFile.isNotEmpty() && newNVRAMFile.isNotEmpty()) 9915 RTFileRename(newNVRAMFile.c_str(), NVRAMFile.c_str(), 0); 9878 9916 } 9879 9917 if (dirRenamed) -
trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp
r80585 r81425 56 56 { 57 57 Guid snapshotUuid; 58 Utf8Str str SaveStateFile;58 Utf8Str strFile; 59 59 ULONG uWeight; 60 } SAVESTATETASK;60 } FILECOPYTASK; 61 61 62 62 // The private class … … 107 107 inline void updateProgressStats(MEDIUMTASKCHAIN &mtc, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) const; 108 108 inline HRESULT addSaveState(const ComObjPtr<Machine> &machine, bool fAttachCurrent, ULONG &uCount, ULONG &uTotalWeight); 109 inline HRESULT addNVRAM(const ComObjPtr<Machine> &machine, bool fAttachCurrent, ULONG &uCount, ULONG &uTotalWeight); 109 110 inline HRESULT queryBaseName(const ComPtr<IMedium> &pMedium, Utf8Str &strBaseName) const; 110 111 HRESULT queryMediasForMachineState(const RTCList<ComObjPtr<Machine> > &machineList, … … 121 122 void updateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const; 122 123 void updateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const; 123 void updateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const; 124 void updateSaveStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const; 125 void updateNVRAMFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const; 124 126 HRESULT createDifferencingMedium(const ComObjPtr<Machine> &pMachine, const ComObjPtr<Medium> &pParent, 125 127 const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, 126 128 ComObjPtr<Medium> *ppDiff) const; 127 static DECLCALLBACK(int) copy StateFileProgress(unsigned uPercentage, void *pvUser);129 static DECLCALLBACK(int) copyFileProgress(unsigned uPercentage, void *pvUser); 128 130 static void updateSnapshotHardwareUUIDs(settings::SnapshotsList &snapshot_list, const Guid &id); 129 131 … … 141 143 RTCList<CloneOptions_T> options; 142 144 RTCList<MEDIUMTASKCHAIN> llMedias; 143 RTCList<SAVESTATETASK> llSaveStateFiles; /* Snapshot UUID -> File path */ 145 RTCList<FILECOPYTASK> llSaveStateFiles; /* Snapshot UUID -> File path */ 146 RTCList<FILECOPYTASK> llNVRAMFiles; /* Snapshot UUID -> File path */ 144 147 }; 145 148 … … 211 214 if (!bstrSrcSaveStatePath.isEmpty()) 212 215 { 213 SAVESTATETASK sst;216 FILECOPYTASK fct; 214 217 if (fAttachCurrent) 215 218 { 216 219 /* Make this saved state part of "current state" of the target 217 220 * machine, whether it is part of a snapshot or not. */ 218 sst.snapshotUuid.clear();221 fct.snapshotUuid.clear(); 219 222 } 220 223 else 221 sst.snapshotUuid = machine->i_getSnapshotId();222 sst.strSaveStateFile = bstrSrcSaveStatePath;224 fct.snapshotUuid = machine->i_getSnapshotId(); 225 fct.strFile = bstrSrcSaveStatePath; 223 226 uint64_t cbSize; 224 int vrc = RTFileQuerySizeByPath( sst.strSaveStateFile.c_str(), &cbSize);227 int vrc = RTFileQuerySizeByPath(fct.strFile.c_str(), &cbSize); 225 228 if (RT_FAILURE(vrc)) 226 229 return p->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, p->tr("Could not query file size of '%s' (%Rrc)"), 227 sst.strSaveStateFile.c_str(), vrc);228 /* 230 fct.strFile.c_str(), vrc); 231 /* same rule as above: count both the data which needs to 229 232 * be read and written */ 230 sst.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M);231 llSaveStateFiles.append( sst);233 fct.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M); 234 llSaveStateFiles.append(fct); 232 235 ++uCount; 233 uTotalWeight += sst.uWeight; 236 uTotalWeight += fct.uWeight; 237 } 238 return S_OK; 239 } 240 241 HRESULT MachineCloneVMPrivate::addNVRAM(const ComObjPtr<Machine> &machine, bool fAttachCurrent, ULONG &uCount, ULONG &uTotalWeight) 242 { 243 Bstr bstrSrcNVRAMPath; 244 ComPtr<IBIOSSettings> pBIOSSettings; 245 HRESULT rc = machine->COMGETTER(BIOSSettings)(pBIOSSettings.asOutParam()); 246 if (FAILED(rc)) return rc; 247 rc = pBIOSSettings->COMGETTER(NonVolatileStorageFile)(bstrSrcNVRAMPath.asOutParam()); 248 if (FAILED(rc)) return rc; 249 if (!bstrSrcNVRAMPath.isEmpty()) 250 { 251 FILECOPYTASK fct; 252 if (fAttachCurrent) 253 { 254 /* Make this saved state part of "current state" of the target 255 * machine, whether it is part of a snapshot or not. */ 256 fct.snapshotUuid.clear(); 257 } 258 else 259 fct.snapshotUuid = machine->i_getSnapshotId(); 260 fct.strFile = bstrSrcNVRAMPath; 261 if (!RTFileExists(fct.strFile.c_str())) 262 return S_OK; 263 uint64_t cbSize; 264 int vrc = RTFileQuerySizeByPath(fct.strFile.c_str(), &cbSize); 265 if (RT_FAILURE(vrc)) 266 return p->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, p->tr("Could not query file size of '%s' (%Rrc)"), 267 fct.strFile.c_str(), vrc); 268 /* same rule as above: count both the data which needs to 269 * be read and written */ 270 fct.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M); 271 llNVRAMFiles.append(fct); 272 ++uCount; 273 uTotalWeight += fct.uWeight; 234 274 } 235 275 return S_OK; … … 322 362 llMedias.append(mtc); 323 363 } 324 /* Add the save state file sof this machine if there is one. */364 /* Add the save state file of this machine if there is one. */ 325 365 rc = addSaveState(machine, true /*fAttachCurrent*/, uCount, uTotalWeight); 366 if (FAILED(rc)) return rc; 367 /* Add the NVRAM file of this machine if there is one. */ 368 rc = addNVRAM(machine, true /*fAttachCurrent*/, uCount, uTotalWeight); 326 369 if (FAILED(rc)) return rc; 327 370 } … … 428 471 llMedias.append(mtc); 429 472 } 430 /* Add the save state file sof this machine if there is one. */473 /* Add the save state file of this machine if there is one. */ 431 474 rc = addSaveState(machine, false /*fAttachCurrent*/, uCount, uTotalWeight); 432 475 if (FAILED(rc)) return rc; 476 /* Add the NVRAM file of this machine if there is one. */ 477 rc = addNVRAM(machine, false /*fAttachCurrent*/, uCount, uTotalWeight); 478 if (FAILED(rc)) return rc; 433 479 /* If this is the newly created current state, make sure that the 434 * saved state is also attached to it. */480 * saved state and NVRAM is also attached to it. */ 435 481 if (fCreateDiffs) 436 482 { 437 483 rc = addSaveState(machine, true /*fAttachCurrent*/, uCount, uTotalWeight); 484 if (FAILED(rc)) return rc; 485 rc = addNVRAM(machine, true /*fAttachCurrent*/, uCount, uTotalWeight); 438 486 if (FAILED(rc)) return rc; 439 487 } … … 576 624 llMedias.append(mtc); 577 625 } 578 /* Add the save state file sof this machine if there is one. */626 /* Add the save state file of this machine if there is one. */ 579 627 rc = addSaveState(machine, false /*fAttachCurrent*/, uCount, uTotalWeight); 628 if (FAILED(rc)) return rc; 629 /* Add the NVRAM file of this machine if there is one. */ 630 rc = addNVRAM(machine, false /*fAttachCurrent*/, uCount, uTotalWeight); 580 631 if (FAILED(rc)) return rc; 581 632 /* If this is the newly created current state, make sure that the … … 584 635 { 585 636 rc = addSaveState(machine, true /*fAttachCurrent*/, uCount, uTotalWeight); 637 if (FAILED(rc)) return rc; 638 rc = addNVRAM(machine, true /*fAttachCurrent*/, uCount, uTotalWeight); 586 639 if (FAILED(rc)) return rc; 587 640 } … … 682 735 } 683 736 684 void MachineCloneVMPrivate::updateS tateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const737 void MachineCloneVMPrivate::updateSaveStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const 685 738 { 686 739 settings::SnapshotsList::iterator it; … … 690 743 it->strStateFile = strFile; 691 744 else if (!it->llChildSnapshots.empty()) 692 updateStateFile(it->llChildSnapshots, id, strFile); 745 updateSaveStateFile(it->llChildSnapshots, id, strFile); 746 } 747 } 748 749 void MachineCloneVMPrivate::updateNVRAMFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const 750 { 751 settings::SnapshotsList::iterator it; 752 for (it = snl.begin(); it != snl.end(); ++it) 753 { 754 if (it->uuid == id) 755 it->hardware.biosSettings.strNVRAMPath = strFile; 756 else if (!it->llChildSnapshots.empty()) 757 updateNVRAMFile(it->llChildSnapshots, id, strFile); 693 758 } 694 759 } … … 753 818 754 819 /* static */ 755 DECLCALLBACK(int) MachineCloneVMPrivate::copy StateFileProgress(unsigned uPercentage, void *pvUser)820 DECLCALLBACK(int) MachineCloneVMPrivate::copyFileProgress(unsigned uPercentage, void *pvUser) 756 821 { 757 822 ComObjPtr<Progress> pProgress = *static_cast< ComObjPtr<Progress>* >(pvUser); … … 1429 1494 for (size_t i = 0; i < d->llSaveStateFiles.size(); ++i) 1430 1495 { 1431 SAVESTATETASK sst = d->llSaveStateFiles.at(i);1496 FILECOPYTASK fct = d->llSaveStateFiles.at(i); 1432 1497 const Utf8Str &strTrgSaveState = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, 1433 RTPathFilename( sst.strSaveStateFile.c_str()));1498 RTPathFilename(fct.strFile.c_str())); 1434 1499 1435 1500 /* Move to next sub-operation. */ 1436 1501 rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Copy save state file '%s' ..."), 1437 RTPathFilename( sst.strSaveStateFile.c_str())).raw(), sst.uWeight);1502 RTPathFilename(fct.strFile.c_str())).raw(), fct.uWeight); 1438 1503 if (FAILED(rc)) throw rc; 1439 1504 /* Copy the file only if it was not copied already. */ 1440 1505 if (!newFiles.contains(strTrgSaveState.c_str())) 1441 1506 { 1442 int vrc = RTFileCopyEx( sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), 0,1443 MachineCloneVMPrivate::copy StateFileProgress, &d->pProgress);1507 int vrc = RTFileCopyEx(fct.strFile.c_str(), strTrgSaveState.c_str(), 0, 1508 MachineCloneVMPrivate::copyFileProgress, &d->pProgress); 1444 1509 if (RT_FAILURE(vrc)) 1445 1510 throw p->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 1446 1511 p->tr("Could not copy state file '%s' to '%s' (%Rrc)"), 1447 sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), vrc);1512 fct.strFile.c_str(), strTrgSaveState.c_str(), vrc); 1448 1513 newFiles.append(strTrgSaveState); 1449 1514 } 1450 1515 /* Update the path in the configuration either for the current 1451 1516 * machine state or the snapshots. */ 1452 if (! sst.snapshotUuid.isValid() || sst.snapshotUuid.isZero())1517 if (!fct.snapshotUuid.isValid() || fct.snapshotUuid.isZero()) 1453 1518 trgMCF.strStateFile = strTrgSaveState; 1454 1519 else 1455 d->updateStateFile(trgMCF.llFirstSnapshot, sst.snapshotUuid, strTrgSaveState); 1520 d->updateSaveStateFile(trgMCF.llFirstSnapshot, fct.snapshotUuid, strTrgSaveState); 1521 } 1522 1523 /* Clone all NVRAM files. */ 1524 for (size_t i = 0; i < d->llNVRAMFiles.size(); ++i) 1525 { 1526 FILECOPYTASK fct = d->llNVRAMFiles.at(i); 1527 Utf8Str strTrgNVRAM; 1528 if (!fct.snapshotUuid.isValid() || fct.snapshotUuid.isZero()) 1529 strTrgNVRAM = Utf8StrFmt("%s%c%s.nvram", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, 1530 trgMCF.machineUserData.strName.c_str()); 1531 else 1532 strTrgNVRAM = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, 1533 RTPathFilename(fct.strFile.c_str())); 1534 1535 /* Move to next sub-operation. */ 1536 rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Copy NVRAM file '%s' ..."), 1537 RTPathFilename(fct.strFile.c_str())).raw(), fct.uWeight); 1538 if (FAILED(rc)) throw rc; 1539 /* Copy the file only if it was not copied already. */ 1540 if (!newFiles.contains(strTrgNVRAM.c_str())) 1541 { 1542 rc = p->i_getVirtualBox()->i_ensureFilePathExists(strTrgNVRAM.c_str(), true); 1543 if (FAILED(rc)) throw rc; 1544 int vrc = RTFileCopyEx(fct.strFile.c_str(), strTrgNVRAM.c_str(), 0, 1545 MachineCloneVMPrivate::copyFileProgress, &d->pProgress); 1546 if (RT_FAILURE(vrc)) 1547 throw p->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 1548 p->tr("Could not copy NVRAM file '%s' to '%s' (%Rrc)"), 1549 fct.strFile.c_str(), strTrgNVRAM.c_str(), vrc); 1550 newFiles.append(strTrgNVRAM); 1551 } 1552 /* Update the path in the configuration either for the current 1553 * machine state or the snapshots. */ 1554 if (!fct.snapshotUuid.isValid() || fct.snapshotUuid.isZero()) 1555 trgMCF.hardwareMachine.biosSettings.strNVRAMPath = strTrgNVRAM; 1556 else 1557 d->updateNVRAMFile(trgMCF.llFirstSnapshot, fct.snapshotUuid, strTrgNVRAM); 1456 1558 } 1457 1559 -
trunk/src/VBox/Main/src-server/MachineImplMoveVM.cpp
r81420 r81425 315 315 ULONG uTotalWeight = 1; 316 316 317 /* The lists m_llMedias and m_llSaveStateFiles are filled in the queryMediasForAllStates() */317 /* The lists m_llMedias, m_llSaveStateFiles and m_llNVRAMFiles are filled in the queryMediasForAllStates() */ 318 318 hrc = queryMediasForAllStates(); 319 319 if (FAILED(hrc)) … … 371 371 { 372 372 uint64_t cbFile = 0; 373 S AVESTATETASKMOVE &sst = m_llSaveStateFiles.at(i);374 375 Utf8Str name = s st.strSaveStateFile;373 SNAPFILETASKMOVE &sft = m_llSaveStateFiles.at(i); 374 375 Utf8Str name = sft.strFile; 376 376 /* if a state file is located in the actual VM folder it will be added to the actual list */ 377 377 if (RTPathStartsWith(name.c_str(), strSettingsFilePath.c_str())) … … 380 380 if (RT_SUCCESS(vrc)) 381 381 { 382 std::pair<std::map<Utf8Str, S AVESTATETASKMOVE>::iterator,bool> ret;383 ret = m_finalSaveStateFilesMap.insert(std::make_pair(name, s st));382 std::pair<std::map<Utf8Str, SNAPFILETASKMOVE>::iterator,bool> ret; 383 ret = m_finalSaveStateFilesMap.insert(std::make_pair(name, sft)); 384 384 if (ret.second == true) 385 385 { 386 386 totalStateSize += cbFile; 387 387 ++uCount; 388 uTotalWeight += s st.uWeight;388 uTotalWeight += sft.uWeight; 389 389 Log2(("The state file %s was added into the moved list\n", name.c_str())); 390 390 } … … 402 402 403 403 neededFreeSpace += totalStateSize; 404 } 405 406 /* Prepare data for moving ".nvram" files */ 407 { 408 uint64_t totalNVRAMSize = 0; 409 410 for (size_t i = 0; i < m_llNVRAMFiles.size(); ++i) 411 { 412 uint64_t cbFile = 0; 413 SNAPFILETASKMOVE &sft = m_llNVRAMFiles.at(i); 414 415 Utf8Str name = sft.strFile; 416 /* if a NVRAM file is located in the actual VM folder it will be added to the actual list */ 417 if (RTPathStartsWith(name.c_str(), strSettingsFilePath.c_str())) 418 { 419 vrc = RTFileQuerySizeByPath(name.c_str(), &cbFile); 420 if (RT_SUCCESS(vrc)) 421 { 422 std::pair<std::map<Utf8Str, SNAPFILETASKMOVE>::iterator,bool> ret; 423 ret = m_finalNVRAMFilesMap.insert(std::make_pair(name, sft)); 424 if (ret.second == true) 425 { 426 totalNVRAMSize += cbFile; 427 ++uCount; 428 uTotalWeight += sft.uWeight; 429 Log2(("The NVRAM file %s was added into the moved list\n", name.c_str())); 430 } 431 } 432 else 433 { 434 Log2(("The NVRAM file %s wasn't added into the moved list. Couldn't get the file size.\n", 435 name.c_str())); 436 return m_pMachine->setErrorVrc(vrc, 437 m_pMachine->tr("Failed to get file size for '%s': %Rrc"), 438 name.c_str(), vrc); 439 } 440 } 441 } 442 443 neededFreeSpace += totalNVRAMSize; 404 444 } 405 445 … … 643 683 /* Check if a snapshot folder is necessary and if so doesn't already 644 684 * exists. */ 645 if ( taskMoveVM->m_finalSaveStateFilesMap.size() != 0 685 if ( ( taskMoveVM->m_finalSaveStateFilesMap.size() > 0 686 || taskMoveVM->m_finalNVRAMFilesMap.size() > 1) 646 687 && !RTDirExists(strTrgSnapshotFolder.c_str())) 647 688 { … … 653 694 } 654 695 655 std::map<Utf8Str, S AVESTATETASKMOVE>::iterator itState = taskMoveVM->m_finalSaveStateFilesMap.begin();696 std::map<Utf8Str, SNAPFILETASKMOVE>::iterator itState = taskMoveVM->m_finalSaveStateFilesMap.begin(); 656 697 while (itState != taskMoveVM->m_finalSaveStateFilesMap.end()) 657 698 { 658 const S AVESTATETASKMOVE &sst = itState->second;699 const SNAPFILETASKMOVE &sft = itState->second; 659 700 const Utf8Str &strTrgSaveState = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, 660 RTPathFilename(s st.strSaveStateFile.c_str()));701 RTPathFilename(sft.strFile.c_str())); 661 702 662 703 /* Move to next sub-operation. */ 663 704 hrc = taskMoveVM->m_pProgress->SetNextOperation(BstrFmt(machine->tr("Copy the save state file '%s' ..."), 664 RTPathFilename(s st.strSaveStateFile.c_str())).raw(),665 s st.uWeight);705 RTPathFilename(sft.strFile.c_str())).raw(), 706 sft.uWeight); 666 707 if (FAILED(hrc)) 667 708 throw hrc; 668 709 669 int vrc = RTFileCopyEx(s st.strSaveStateFile.c_str(), strTrgSaveState.c_str(), 0,710 int vrc = RTFileCopyEx(sft.strFile.c_str(), strTrgSaveState.c_str(), 0, 670 711 MachineMoveVM::copyFileProgress, &taskMoveVM->m_pProgress); 671 712 if (RT_FAILURE(vrc)) 672 713 throw machine->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 673 714 taskMoveVM->m_pMachine->tr("Could not copy state file '%s' to '%s' (%Rrc)"), 674 s st.strSaveStateFile.c_str(),715 sft.strFile.c_str(), 675 716 strTrgSaveState.c_str(), 676 717 vrc); … … 679 720 newFiles.append(strTrgSaveState); 680 721 /* save original file for deletion in the end */ 681 originalFiles.append(s st.strSaveStateFile);722 originalFiles.append(sft.strFile); 682 723 ++itState; 724 } 725 726 std::map<Utf8Str, SNAPFILETASKMOVE>::iterator itNVRAM = taskMoveVM->m_finalNVRAMFilesMap.begin(); 727 while (itNVRAM != taskMoveVM->m_finalNVRAMFilesMap.end()) 728 { 729 const SNAPFILETASKMOVE &sft = itNVRAM->second; 730 const Utf8Str &strTrgNVRAM = Utf8StrFmt("%s%c%s", sft.snapshotUuid.isZero() ? strTargetFolder.c_str() : strTrgSnapshotFolder.c_str(), 731 RTPATH_DELIMITER, RTPathFilename(sft.strFile.c_str())); 732 733 /* Move to next sub-operation. */ 734 hrc = taskMoveVM->m_pProgress->SetNextOperation(BstrFmt(machine->tr("Copy the NVRAM file '%s' ..."), 735 RTPathFilename(sft.strFile.c_str())).raw(), 736 sft.uWeight); 737 if (FAILED(hrc)) 738 throw hrc; 739 740 int vrc = RTFileCopyEx(sft.strFile.c_str(), strTrgNVRAM.c_str(), 0, 741 MachineMoveVM::copyFileProgress, &taskMoveVM->m_pProgress); 742 if (RT_FAILURE(vrc)) 743 throw machine->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 744 taskMoveVM->m_pMachine->tr("Could not copy NVRAM file '%s' to '%s' (%Rrc)"), 745 sft.strFile.c_str(), 746 strTrgNVRAM.c_str(), 747 vrc); 748 749 /* save new file in case of restoring */ 750 newFiles.append(strTrgNVRAM); 751 /* save original file for deletion in the end */ 752 originalFiles.append(sft.strFile); 753 ++itNVRAM; 683 754 } 684 755 } … … 695 766 696 767 /* 768 * Update NVRAM file paths 769 * very important step! 770 */ 771 Log2(("Update NVRAM paths\n")); 772 /** @todo r=klaus: this update is not necessarily matching what the 773 * above code has set as the new folders, so it needs reimplementing. 774 * What's good about this implementation: it does not look at the 775 * list of NVRAM files, because that only lists the existing ones, 776 * but all paths need fixing. */ 777 taskMoveVM->updatePathsToNVRAMFiles(taskMoveVM->m_vmFolders[VBox_SettingFolder], 778 strTargetFolder); 779 780 /* 697 781 * Moving Machine settings file 698 782 * The settings file are moved after all disks and snapshots because this file should be updated … … 753 837 /* save original file for deletion in the end */ 754 838 originalFiles.append(strSettingsFilePath); 839 840 Utf8Str strPrevSettingsFilePath = strSettingsFilePath; 841 strPrevSettingsFilePath.append("-prev"); 842 if (RTFileExists(strPrevSettingsFilePath.c_str())) 843 originalFiles.append(strPrevSettingsFilePath); 755 844 } 756 845 … … 921 1010 taskMoveVM->m_vmFolders[VBox_SettingFolder]); 922 1011 1012 /* Revert original paths to the NVRAM files */ 1013 taskMoveVM->updatePathsToNVRAMFiles(strTargetFolder, 1014 taskMoveVM->m_vmFolders[VBox_SettingFolder]); 1015 923 1016 /* Delete all created files. Here we update progress object */ 924 1017 hrc = taskMoveVM->deleteFiles(newFiles); … … 1159 1252 RTPATH_DELIMITER, 1160 1253 RTPathFilename(m_pMachine->mSSData->strStateFilePath.c_str())); 1254 } 1255 } 1256 1257 void MachineMoveVM::updatePathsToNVRAMFiles(const Utf8Str &sourcePath, const Utf8Str &targetPath) 1258 { 1259 ComObjPtr<Snapshot> pSnapshot; 1260 HRESULT rc = m_pMachine->i_findSnapshotById(Guid() /* zero */, pSnapshot, true); 1261 if (SUCCEEDED(rc) && !pSnapshot.isNull()) 1262 pSnapshot->i_updateNVRAMPaths(sourcePath.c_str(), 1263 targetPath.c_str()); 1264 ComObjPtr<BIOSSettings> pBIOSSettings(m_pMachine->mBIOSSettings); 1265 const Utf8Str NVRAMFile(pBIOSSettings->i_getNonVolatileStorageFile()); 1266 if (NVRAMFile.isNotEmpty()) 1267 { 1268 Utf8Str newNVRAMFile; 1269 if (RTPathStartsWith(NVRAMFile.c_str(), sourcePath.c_str())) 1270 newNVRAMFile = Utf8StrFmt("%s%s", targetPath.c_str(), NVRAMFile.c_str() + sourcePath.length()); 1271 else 1272 newNVRAMFile = Utf8StrFmt("%s%c%s", targetPath.c_str(), RTPATH_DELIMITER, RTPathFilename(newNVRAMFile.c_str())); 1273 pBIOSSettings->i_updateNonVolatileStorageFile(newNVRAMFile); 1161 1274 } 1162 1275 } … … 1420 1533 rc = addSaveState(machine); 1421 1534 if (FAILED(rc)) return rc; 1535 1536 /* Add the NVRAM files of this machine if there is one. */ 1537 rc = addNVRAM(machine); 1538 if (FAILED(rc)) return rc; 1422 1539 } 1423 1540 … … 1443 1560 if (!bstrSrcSaveStatePath.isEmpty()) 1444 1561 { 1445 S AVESTATETASKMOVE sst;1446 1447 s st.snapshotUuid = machine->i_getSnapshotId();1448 s st.strSaveStateFile = bstrSrcSaveStatePath;1562 SNAPFILETASKMOVE sft; 1563 1564 sft.snapshotUuid = machine->i_getSnapshotId(); 1565 sft.strFile = bstrSrcSaveStatePath; 1449 1566 uint64_t cbSize; 1450 1567 1451 int vrc = RTFileQuerySizeByPath(s st.strSaveStateFile.c_str(), &cbSize);1568 int vrc = RTFileQuerySizeByPath(sft.strFile.c_str(), &cbSize); 1452 1569 if (RT_FAILURE(vrc)) 1453 1570 return m_pMachine->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 1454 1571 m_pMachine->tr("Could not get file size of '%s': %Rrc"), 1455 s st.strSaveStateFile.c_str(),1572 sft.strFile.c_str(), 1456 1573 vrc); 1457 1574 1458 1575 /* same rule as above: count both the data which needs to 1459 1576 * be read and written */ 1460 sst.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M); 1461 m_llSaveStateFiles.append(sst); 1577 sft.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M); 1578 m_llSaveStateFiles.append(sft); 1579 } 1580 return S_OK; 1581 } 1582 1583 HRESULT MachineMoveVM::addNVRAM(const ComObjPtr<Machine> &machine) 1584 { 1585 ComPtr<IBIOSSettings> pBIOSSettings; 1586 HRESULT rc = machine->COMGETTER(BIOSSettings)(pBIOSSettings.asOutParam()); 1587 if (FAILED(rc)) return rc; 1588 Bstr bstrSrcNVRAMPath; 1589 rc = pBIOSSettings->COMGETTER(NonVolatileStorageFile)(bstrSrcNVRAMPath.asOutParam()); 1590 if (FAILED(rc)) return rc; 1591 Utf8Str strSrcNVRAMPath(bstrSrcNVRAMPath); 1592 if (!strSrcNVRAMPath.isEmpty() && RTFileExists(strSrcNVRAMPath.c_str())) 1593 { 1594 SNAPFILETASKMOVE sft; 1595 1596 sft.snapshotUuid = machine->i_getSnapshotId(); 1597 sft.strFile = strSrcNVRAMPath; 1598 uint64_t cbSize; 1599 1600 int vrc = RTFileQuerySizeByPath(sft.strFile.c_str(), &cbSize); 1601 if (RT_FAILURE(vrc)) 1602 return m_pMachine->setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 1603 m_pMachine->tr("Could not get file size of '%s': %Rrc"), 1604 sft.strFile.c_str(), 1605 vrc); 1606 1607 /* same rule as above: count both the data which needs to 1608 * be read and written */ 1609 sft.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M); 1610 m_llNVRAMFiles.append(sft); 1462 1611 } 1463 1612 return S_OK; -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r79154 r81425 656 656 657 657 /* state file may be NULL (for offline snapshots) */ 658 if ( path. length()658 if ( path.isNotEmpty() 659 659 && RTPathStartsWith(path.c_str(), strOldPath.c_str()) 660 660 ) … … 663 663 strNewPath.c_str(), 664 664 path.c_str() + strOldPath.length()); 665 LogFlowThisFunc(("-> updated: {%s}\n", path.c_str()));665 LogFlowThisFunc(("-> updated: {%s}\n", m->pMachine->mSSData->strStateFilePath.c_str())); 666 666 } 667 667 … … 673 673 pChild->i_updateSavedStatePathsImpl(strOldPath, strNewPath); 674 674 } 675 } 676 677 /** 678 * Checks if the specified path change affects the saved state file path of 679 * this snapshot or any of its (grand-)children and updates it accordingly. 680 * 681 * Intended to be called by Machine::openConfigLoader() only. 682 * 683 * @param strOldPath old path (full) 684 * @param strNewPath new path (full) 685 * 686 * @note Locks the machine (for the snapshots tree) + this object + children for writing. 687 */ 688 void Snapshot::i_updateSavedStatePaths(const Utf8Str &strOldPath, 689 const Utf8Str &strNewPath) 690 { 691 LogFlowThisFunc(("aOldPath={%s} aNewPath={%s}\n", strOldPath.c_str(), strNewPath.c_str())); 692 693 AutoCaller autoCaller(this); 694 AssertComRC(autoCaller.rc()); 695 696 // snapshots tree is protected by machine lock 697 AutoWriteLock alock(m->pMachine COMMA_LOCKVAL_SRC_POS); 698 699 // call the implementation under the tree lock 700 i_updateSavedStatePathsImpl(strOldPath, strNewPath); 675 701 } 676 702 … … 714 740 715 741 /** 716 * Checks if the specified path change affects the saved state file path of 742 * Internal implementation for Snapshot::updateNVRAMPaths (below). 743 * @param strOldPath 744 * @param strNewPath 745 */ 746 void Snapshot::i_updateNVRAMPathsImpl(const Utf8Str &strOldPath, 747 const Utf8Str &strNewPath) 748 { 749 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 750 751 const Utf8Str path = m->pMachine->mBIOSSettings->i_getNonVolatileStorageFile(); 752 LogFlowThisFunc(("Snap[%s].nvramPath={%s}\n", m->strName.c_str(), path.c_str())); 753 754 /* NVRAM filename may be empty */ 755 if ( path.isNotEmpty() 756 && RTPathStartsWith(path.c_str(), strOldPath.c_str()) 757 ) 758 { 759 m->pMachine->mBIOSSettings->i_updateNonVolatileStorageFile(Utf8StrFmt("%s%s", 760 strNewPath.c_str(), 761 path.c_str() + strOldPath.length())); 762 LogFlowThisFunc(("-> updated: {%s}\n", m->pMachine->mBIOSSettings->i_getNonVolatileStorageFile().c_str())); 763 } 764 765 for (SnapshotsList::const_iterator it = m->llChildren.begin(); 766 it != m->llChildren.end(); 767 ++it) 768 { 769 Snapshot *pChild = *it; 770 pChild->i_updateNVRAMPathsImpl(strOldPath, strNewPath); 771 } 772 } 773 774 /** 775 * Checks if the specified path change affects the NVRAM file path of 717 776 * this snapshot or any of its (grand-)children and updates it accordingly. 718 777 * … … 724 783 * @note Locks the machine (for the snapshots tree) + this object + children for writing. 725 784 */ 726 void Snapshot::i_update SavedStatePaths(const Utf8Str &strOldPath,727 785 void Snapshot::i_updateNVRAMPaths(const Utf8Str &strOldPath, 786 const Utf8Str &strNewPath) 728 787 { 729 788 LogFlowThisFunc(("aOldPath={%s} aNewPath={%s}\n", strOldPath.c_str(), strNewPath.c_str())); … … 844 903 845 904 // report the saved state file if it's not on the list yet 846 if ( !m->pMachine->mSSData->strStateFilePath.isEmpty())905 if (m->pMachine->mSSData->strStateFilePath.isNotEmpty()) 847 906 { 848 907 bool fFound = false; … … 861 920 llFilenames.push_back(m->pMachine->mSSData->strStateFilePath); 862 921 } 922 923 Utf8Str strNVRAMFile = m->pMachine->mBIOSSettings->i_getNonVolatileStorageFile(); 924 if (strNVRAMFile.isNotEmpty() && RTFileExists(strNVRAMFile.c_str())) 925 llFilenames.push_back(strNVRAMFile); 863 926 864 927 i_beginSnapshotDelete(); … … 1782 1845 if (FAILED(rc)) 1783 1846 throw rc; 1847 } 1848 1849 // Handle NVRAM file snapshotting 1850 Utf8Str strNVRAM = mBIOSSettings->i_getNonVolatileStorageFile(); 1851 Utf8Str strNVRAMSnap = pSnapshotMachine->i_getSnapshotNVRAMFilename(); 1852 Utf8Str strNVRAMSnapAbs; 1853 i_calculateFullPath(strNVRAMSnap, strNVRAMSnapAbs); 1854 if (strNVRAM.isNotEmpty() && strNVRAMSnap.isNotEmpty() && RTFileExists(strNVRAM.c_str())) 1855 { 1856 rc = VirtualBox::i_ensureFilePathExists(strNVRAMSnapAbs, true /* fCreate */); 1857 if (FAILED(rc)) 1858 throw rc; 1859 int vrc = RTFileCopy(strNVRAM.c_str(), strNVRAMSnapAbs.c_str()); 1860 if (RT_FAILURE(vrc)) 1861 throw setErrorBoth(VBOX_E_IPRT_ERROR, vrc, 1862 tr("Could not copy NVRAM file '%s' to '%s' (%Rrc)"), 1863 strNVRAM.c_str(), strNVRAMSnapAbs.c_str(), vrc); 1864 pSnapshotMachine->mBIOSSettings->i_updateNonVolatileStorageFile(strNVRAMSnap); 1784 1865 } 1785 1866 … … 2276 2357 mSSData->strStateFilePath = strSnapshotStateFile; 2277 2358 2359 const Utf8Str srcNVRAM(pSnapshotMachine->mBIOSSettings->i_getNonVolatileStorageFile()); 2360 const Utf8Str dstNVRAM(mBIOSSettings->i_getNonVolatileStorageFile()); 2361 if (dstNVRAM.isNotEmpty() && RTFileExists(dstNVRAM.c_str())) 2362 RTFileDelete(dstNVRAM.c_str()); 2363 if (srcNVRAM.isNotEmpty() && dstNVRAM.isNotEmpty() && RTFileExists(srcNVRAM.c_str())) 2364 RTFileCopy(srcNVRAM.c_str(), dstNVRAM.c_str()); 2365 2278 2366 LogFlowThisFunc(("Setting new current snapshot {%RTuuid}\n", task.m_pSnapshot->i_getId().raw())); 2279 2367 /* make the snapshot we restored from the current snapshot */ … … 2621 2709 ULONG ulTotalWeight = 1; // one for preparations 2622 2710 2623 if (pSnapshot->i_getStateFilePath(). length())2711 if (pSnapshot->i_getStateFilePath().isNotEmpty()) 2624 2712 { 2625 2713 ++ulOpCount; … … 3391 3479 } 3392 3480 3481 /* 3a: delete NVRAM file if present. */ 3482 { 3483 Utf8Str NVRAMPath = pSnapMachine->mBIOSSettings->i_getNonVolatileStorageFile(); 3484 if (NVRAMPath.isNotEmpty() && RTFileExists(NVRAMPath.c_str())) 3485 RTFileDelete(NVRAMPath.c_str()); 3486 } 3487 3488 /* third pass: */ 3393 3489 { 3394 3490 // beginSnapshotDelete() needs the machine lock, and the snapshots
Note:
See TracChangeset
for help on using the changeset viewer.