Changeset 67249 in vbox for trunk/src/VBox/Main/src-server/MediumImpl.cpp
- Timestamp:
- Jun 2, 2017 3:24:58 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 115944
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r67244 r67249 651 651 }; 652 652 653 #ifndef VBOX_WITH_NEW_TAR_CREATOR654 class Medium::ExportTask : public Medium::Task655 {656 public:657 ExportTask(Medium *aMedium,658 Progress *aProgress,659 const char *aFilename,660 MediumFormat *aFormat,661 MediumVariant_T aVariant,662 SecretKeyStore *pSecretKeyStore,663 VDINTERFACEIO *aVDImageIOIf,664 void *aVDImageIOUser,665 MediumLockList *aSourceMediumLockList,666 bool fKeepSourceMediumLockList = false)667 : Medium::Task(aMedium, aProgress),668 mpSourceMediumLockList(aSourceMediumLockList),669 mFilename(aFilename),670 mFormat(aFormat),671 mVariant(aVariant),672 m_pSecretKeyStore(pSecretKeyStore),673 mfKeepSourceMediumLockList(fKeepSourceMediumLockList)674 {675 AssertReturnVoidStmt(aSourceMediumLockList != NULL, mRC = E_FAIL);676 677 mVDImageIfaces = aMedium->m->vdImageIfaces;678 679 if (aVDImageIOIf)680 {681 int vrc = VDInterfaceAdd(&aVDImageIOIf->Core, "Medium::vdInterfaceIO",682 VDINTERFACETYPE_IO, aVDImageIOUser,683 sizeof(VDINTERFACEIO), &mVDImageIfaces);684 AssertRCReturnVoidStmt(vrc, mRC = E_FAIL);685 }686 m_strTaskName = "createExport";687 }688 689 ~ExportTask()690 {691 if (!mfKeepSourceMediumLockList && mpSourceMediumLockList)692 delete mpSourceMediumLockList;693 }694 695 MediumLockList *mpSourceMediumLockList;696 Utf8Str mFilename;697 ComObjPtr<MediumFormat> mFormat;698 MediumVariant_T mVariant;699 PVDINTERFACE mVDImageIfaces;700 SecretKeyStore *m_pSecretKeyStore;701 702 private:703 HRESULT executeTask();704 bool mfKeepSourceMediumLockList;705 };706 #endif /* !VBOX_WITH_NEW_TAR_CREATOR */707 708 653 class Medium::ImportTask : public Medium::Task 709 654 { … … 956 901 return mMedium->i_taskMergeHandler(*this); 957 902 } 958 959 #ifndef VBOX_WITH_NEW_TAR_CREATOR960 /**961 * Implementation code for the "export" task.962 */963 HRESULT Medium::ExportTask::executeTask()964 {965 return mMedium->i_taskExportHandler(*this);966 }967 #endif968 903 969 904 /** … … 6141 6076 * @param pKeyStore The optional key store for decrypting the data for 6142 6077 * encrypted media during the export. 6143 * @param aVDImageIOIf Pointer to the callback table for a VDINTERFACEIO 6144 * interface. May be NULL. 6145 * @param aVDImageIOUser Opaque data for the callbacks. 6078 * @param hVfsIosDst The destination I/O stream object. 6146 6079 * @param aProgress Progress object to use. 6147 6080 * @return … … 6153 6086 MediumVariant_T aVariant, 6154 6087 SecretKeyStore *pKeyStore, 6155 #ifdef VBOX_WITH_NEW_TAR_CREATOR6156 6088 RTVFSIOSTREAM hVfsIosDst, 6157 #else6158 PVDINTERFACEIO aVDImageIOIf, void *aVDImageIOUser,6159 #endif6160 6089 const ComObjPtr<Progress> &aProgress) 6161 6090 { … … 6163 6092 AssertReturn(aFormat.isNotNull(), E_INVALIDARG); 6164 6093 AssertReturn(aProgress.isNotNull(), E_INVALIDARG); 6165 6166 #ifdef VBOX_WITH_NEW_TAR_CREATOR6167 6094 6168 6095 AutoCaller autoCaller(this); … … 6256 6183 } 6257 6184 return hrc; 6258 #else6259 6260 AutoCaller autoCaller(this);6261 if (FAILED(autoCaller.rc())) return autoCaller.rc();6262 6263 HRESULT rc = S_OK;6264 Medium::Task *pTask = NULL;6265 6266 try6267 {6268 // This needs no extra locks besides what is done in the called methods.6269 6270 /* Build the source lock list. */6271 MediumLockList *pSourceMediumLockList(new MediumLockList());6272 rc = i_createMediumLockList(true /* fFailIfInaccessible */,6273 NULL /* pToLockWrite */,6274 false /* fMediumLockWriteAll */,6275 NULL,6276 *pSourceMediumLockList);6277 if (FAILED(rc))6278 {6279 delete pSourceMediumLockList;6280 throw rc;6281 }6282 6283 rc = pSourceMediumLockList->Lock();6284 if (FAILED(rc))6285 {6286 delete pSourceMediumLockList;6287 throw setError(rc,6288 tr("Failed to lock source media '%s'"),6289 i_getLocationFull().c_str());6290 }6291 6292 /* setup task object to carry out the operation asynchronously */6293 pTask = new Medium::ExportTask(this, aProgress, aFilename, aFormat, aVariant,6294 pKeyStore, aVDImageIOIf, aVDImageIOUser, pSourceMediumLockList);6295 rc = pTask->rc();6296 AssertComRC(rc);6297 if (FAILED(rc))6298 throw rc;6299 }6300 catch (HRESULT aRC) { rc = aRC; }6301 6302 if (SUCCEEDED(rc))6303 rc = pTask->createThread();6304 else if (pTask != NULL)6305 delete pTask;6306 6307 return rc;6308 #endif6309 6185 } 6310 6186 … … 9767 9643 } 9768 9644 9769 #ifndef VBOX_WITH_NEW_TAR_CREATOR9770 /**9771 * Implementation code for the "export" task.9772 *9773 * This only gets started from Medium::exportFile() and always runs9774 * asynchronously. It doesn't touch anything configuration related, so9775 * we never save the VirtualBox.xml file here.9776 *9777 * @param task9778 * @return9779 */9780 HRESULT Medium::i_taskExportHandler(Medium::ExportTask &task)9781 {9782 HRESULT rc = S_OK;9783 9784 try9785 {9786 /* Lock all in {parent,child} order. The lock is also used as a9787 * signal from the task initiator (which releases it only after9788 * RTThreadCreate()) that we can start the job. */9789 ComObjPtr<Medium> pBase = i_getBase();9790 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);9791 9792 PVDISK hdd;9793 int vrc = VDCreate(m->vdDiskIfaces, i_convertDeviceType(), &hdd);9794 ComAssertRCThrow(vrc, E_FAIL);9795 9796 try9797 {9798 settings::StringsMap::iterator itKeyStore = pBase->m->mapProperties.find("CRYPT/KeyStore");9799 if (itKeyStore != pBase->m->mapProperties.end())9800 {9801 settings::StringsMap::iterator itKeyId = pBase->m->mapProperties.find("CRYPT/KeyId");9802 9803 #ifdef VBOX_WITH_EXTPACK9804 ExtPackManager *pExtPackManager = m->pVirtualBox->i_getExtPackManager();9805 if (pExtPackManager->i_isExtPackUsable(ORACLE_PUEL_EXTPACK_NAME))9806 {9807 /* Load the plugin */9808 Utf8Str strPlugin;9809 rc = pExtPackManager->i_getLibraryPathForExtPack(g_szVDPlugin, ORACLE_PUEL_EXTPACK_NAME, &strPlugin);9810 if (SUCCEEDED(rc))9811 {9812 vrc = VDPluginLoadFromFilename(strPlugin.c_str());9813 if (RT_FAILURE(vrc))9814 throw setError(VBOX_E_NOT_SUPPORTED,9815 tr("Retrieving encryption settings of the image failed because the encryption plugin could not be loaded (%s)"),9816 i_vdError(vrc).c_str());9817 }9818 else9819 throw setError(VBOX_E_NOT_SUPPORTED,9820 tr("Encryption is not supported because the extension pack '%s' is missing the encryption plugin (old extension pack installed?)"),9821 ORACLE_PUEL_EXTPACK_NAME);9822 }9823 else9824 throw setError(VBOX_E_NOT_SUPPORTED,9825 tr("Encryption is not supported because the extension pack '%s' is missing"),9826 ORACLE_PUEL_EXTPACK_NAME);9827 #else9828 throw setError(VBOX_E_NOT_SUPPORTED,9829 tr("Encryption is not supported because extension pack support is not built in"));9830 #endif9831 9832 if (itKeyId == pBase->m->mapProperties.end())9833 throw setError(VBOX_E_INVALID_OBJECT_STATE,9834 tr("Image '%s' is configured for encryption but doesn't has a key identifier set"),9835 pBase->m->strLocationFull.c_str());9836 9837 /* Find the proper secret key in the key store. */9838 if (!task.m_pSecretKeyStore)9839 throw setError(VBOX_E_INVALID_OBJECT_STATE,9840 tr("Image '%s' is configured for encryption but there is no key store to retrieve the password from"),9841 pBase->m->strLocationFull.c_str());9842 9843 SecretKey *pKey = NULL;9844 vrc = task.m_pSecretKeyStore->retainSecretKey(itKeyId->second, &pKey);9845 if (RT_FAILURE(vrc))9846 throw setError(VBOX_E_INVALID_OBJECT_STATE,9847 tr("Failed to retrieve the secret key with ID \"%s\" from the store (%Rrc)"),9848 itKeyId->second.c_str(), vrc);9849 9850 /** @todo r=bird: Someone explain why this continue to work when9851 * CryptoSettingsRead goes out of the scope? */9852 Medium::CryptoFilterSettings CryptoSettingsRead;9853 i_taskEncryptSettingsSetup(&CryptoSettingsRead, NULL, itKeyStore->second.c_str(), (const char *)pKey->getKeyBuffer(),9854 false /* fCreateKeyStore */);9855 vrc = VDFilterAdd(hdd, "CRYPT", VD_FILTER_FLAGS_READ, CryptoSettingsRead.vdFilterIfaces);9856 if (vrc == VERR_VD_PASSWORD_INCORRECT)9857 {9858 task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);9859 throw setError(VBOX_E_PASSWORD_INCORRECT,9860 tr("The password to decrypt the image is incorrect"));9861 }9862 else if (RT_FAILURE(vrc))9863 {9864 task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);9865 throw setError(VBOX_E_INVALID_OBJECT_STATE,9866 tr("Failed to load the decryption filter: %s"),9867 i_vdError(vrc).c_str());9868 }9869 9870 task.m_pSecretKeyStore->releaseSecretKey(itKeyId->second);9871 }9872 9873 /* Open all media in the source chain. */9874 MediumLockList::Base::const_iterator sourceListBegin =9875 task.mpSourceMediumLockList->GetBegin();9876 MediumLockList::Base::const_iterator sourceListEnd =9877 task.mpSourceMediumLockList->GetEnd();9878 for (MediumLockList::Base::const_iterator it = sourceListBegin;9879 it != sourceListEnd;9880 ++it)9881 {9882 const MediumLock &mediumLock = *it;9883 const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium();9884 AutoReadLock alock(pMedium COMMA_LOCKVAL_SRC_POS);9885 9886 /* sanity check */9887 Assert(pMedium->m->state == MediumState_LockedRead);9888 9889 /* Open all media in read-only mode. */9890 vrc = VDOpen(hdd,9891 pMedium->m->strFormat.c_str(),9892 pMedium->m->strLocationFull.c_str(),9893 VD_OPEN_FLAGS_READONLY | m->uOpenFlagsDef,9894 pMedium->m->vdImageIfaces);9895 if (RT_FAILURE(vrc))9896 throw setError(VBOX_E_FILE_ERROR,9897 tr("Could not open the medium storage unit '%s'%s"),9898 pMedium->m->strLocationFull.c_str(),9899 i_vdError(vrc).c_str());9900 }9901 9902 Utf8Str targetFormat(task.mFormat->i_getId());9903 Utf8Str targetLocation(task.mFilename);9904 uint64_t capabilities = task.mFormat->i_getCapabilities();9905 9906 Assert(m->state == MediumState_LockedRead);9907 9908 /* unlock before the potentially lengthy operation */9909 thisLock.release();9910 9911 /* ensure the target directory exists */9912 if (capabilities & MediumFormatCapabilities_File)9913 {9914 rc = VirtualBox::i_ensureFilePathExists(targetLocation,9915 !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */);9916 if (FAILED(rc))9917 throw rc;9918 }9919 9920 PVDISK targetHdd;9921 vrc = VDCreate(m->vdDiskIfaces, i_convertDeviceType(), &targetHdd);9922 ComAssertRCThrow(vrc, E_FAIL);9923 9924 try9925 {9926 vrc = VDCopy(hdd,9927 VD_LAST_IMAGE,9928 targetHdd,9929 targetFormat.c_str(),9930 targetLocation.c_str(),9931 false /* fMoveByRename */,9932 0 /* cbSize */,9933 task.mVariant & ~MediumVariant_NoCreateDir,9934 NULL /* pDstUuid */,9935 VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_SEQUENTIAL,9936 NULL /* pVDIfsOperation */,9937 task.mVDImageIfaces,9938 task.mVDOperationIfaces);9939 if (RT_FAILURE(vrc))9940 throw setError(VBOX_E_FILE_ERROR,9941 tr("Could not create the exported medium '%s'%s"),9942 targetLocation.c_str(), i_vdError(vrc).c_str());9943 }9944 catch (HRESULT aRC) { rc = aRC; }9945 9946 VDDestroy(targetHdd);9947 }9948 catch (HRESULT aRC) { rc = aRC; }9949 9950 VDDestroy(hdd);9951 }9952 catch (HRESULT aRC) { rc = aRC; }9953 9954 /* Everything is explicitly unlocked when the task exits,9955 * as the task destruction also destroys the source chain. */9956 9957 /* Make sure the source chain is released early, otherwise it can9958 * lead to deadlocks with concurrent IAppliance activities. */9959 task.mpSourceMediumLockList->Clear();9960 9961 return rc;9962 }9963 #endif /* !VBOX_WITH_NEW_TAR_CREATOR */9964 9965 9645 /** 9966 9646 * Implementation code for the "import" task.
Note:
See TracChangeset
for help on using the changeset viewer.