- Timestamp:
- Apr 1, 2008 5:51:08 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VBoxHDD-new.cpp
r7281 r7690 1576 1576 PFNVMPROGRESS pfnProgress, void *pvUser) 1577 1577 { 1578 return VERR_NOT_IMPLEMENTED; 1578 int rc, rc2 = VINF_SUCCESS; 1579 void *pvBuf = NULL; 1580 PVDIMAGE pImageTo = NULL; 1581 1582 LogFlowFunc(("pDiskFrom=%#p nImage=%u pDiskTo=%#p pszBackend=\"%s\" pszFilename=\"%s\" fMoveByRename=%d cbSize=%llu pfnProgress=%#p pvUser=%#p\n", 1583 pDiskFrom, nImage, pDiskTo, pszBackend, pszFilename, fMoveByRename, cbSize, pfnProgress, pvUser)); 1584 1585 do { 1586 /* Check arguments. */ 1587 AssertMsgBreak(VALID_PTR(pDiskFrom), ("pDiskFrom=%#p\n", pDiskFrom), 1588 rc = VERR_INVALID_PARAMETER); 1589 AssertMsg(pDiskFrom->u32Signature == VBOXHDDDISK_SIGNATURE, 1590 ("u32Signature=%08x\n", pDiskFrom->u32Signature)); 1591 1592 PVDIMAGE pImageFrom = vdGetImageByNumber(pDiskFrom, nImage); 1593 AssertBreak(VALID_PTR(pImageFrom), rc = VERR_VDI_IMAGE_NOT_FOUND); 1594 AssertMsgBreak(VALID_PTR(pDiskTo), ("pDiskTo=%#p\n", pDiskTo), 1595 rc = VERR_INVALID_PARAMETER); 1596 AssertMsg(pDiskTo->u32Signature == VBOXHDDDISK_SIGNATURE, 1597 ("u32Signature=%08x\n", pDiskTo->u32Signature)); 1598 1599 /* If the containers are equal and the backend is the same, rename the image. */ 1600 if ( (pDiskFrom == pDiskTo) 1601 && (!strcmp(pszBackend, pImageFrom->Backend->pszBackendName))) 1602 { 1603 /* Rename the image. */ 1604 rc = pImageFrom->Backend->pfnRename(pImageFrom->pvBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename); 1605 break; 1606 } 1607 1608 /* If the fMoveByRename flag is set and the backend is the same, rename the image. */ 1609 if ( (fMoveByRename == true) 1610 && (!strcmp(pszBackend, pImageFrom->Backend->pszBackendName))) 1611 { 1612 /* Close the source image. */ 1613 rc = pImageFrom->Backend->pfnClose(pImageFrom->pvBackendData, false); 1614 if (VBOX_FAILURE(rc)) 1615 break; 1616 1617 /* Open the source image in the destination container. */ 1618 rc = VDOpen(pDiskTo, pImageFrom->Backend->pszBackendName, pImageFrom->pszFilename, pImageFrom->uOpenFlags); 1619 if (VBOX_FAILURE(rc)) 1620 goto movefail; 1621 1622 pImageTo = pDiskTo->pLast; 1623 1624 /* Rename the image. */ 1625 rc = pImageTo->Backend->pfnRename(pImageTo->pvBackendData, pszFilename ? pszFilename : pImageTo->pszFilename); 1626 if (VBOX_FAILURE(rc)) 1627 goto movefail; 1628 1629 /* Cleanup the leftovers. */ 1630 vdRemoveImageFromList(pDiskFrom, pImageFrom); 1631 pImageFrom->pvBackendData = NULL; 1632 1633 if (pImageFrom->hPlugin != NIL_RTLDRMOD) 1634 RTLdrClose(pImageFrom->hPlugin); 1635 1636 if (pImageFrom->pszFilename) 1637 RTStrFree(pImageFrom->pszFilename); 1638 1639 RTMemFree(pImageFrom); 1640 1641 break; 1642 movefail: 1643 /* In case of failure, re-open the source image in the source container. */ 1644 rc2 = VDOpen(pDiskFrom, pImageFrom->Backend->pszBackendName, pImageFrom->pszFilename, pImageFrom->uOpenFlags); 1645 if (VBOX_FAILURE(rc2)) 1646 /* @todo Uncertain what to do on error. If this happens pImageFrom and pImageTo are both closed. */ 1647 rc = rc2; 1648 break; 1649 } 1650 1651 /* If fMoveByRename is set pszFilename is allowed to be NULL, so do the parameter check here. */ 1652 AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename, 1653 ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename), 1654 rc = VERR_INVALID_PARAMETER); 1655 1656 /* Collect properties of source image. */ 1657 VDIMAGETYPE enmTypeFrom; 1658 rc = VDGetImageType(pDiskFrom, nImage, &enmTypeFrom); 1659 if (VBOX_FAILURE(rc)) 1660 break; 1661 1662 uint64_t cbSizeFrom = VDGetSize(pDiskFrom, nImage); 1663 if (cbSizeFrom == 0) 1664 { 1665 rc = VERR_VDI_VALUE_NOT_FOUND; 1666 break; 1667 } 1668 1669 if (cbSize == 0) 1670 cbSize = cbSizeFrom; 1671 1672 unsigned uImageFlagsFrom; 1673 rc = VDGetImageFlags(pDiskFrom, nImage, &uImageFlagsFrom); 1674 if (VBOX_FAILURE(rc)) 1675 break; 1676 1677 /* @todo Get this from the source image. */ 1678 PDMMEDIAGEOMETRY PCHSGeometryFrom = {0, 0, 0}; 1679 PDMMEDIAGEOMETRY LCHSGeometryFrom = {0, 0, 0}; 1680 1681 unsigned uOpenFlagsFrom; 1682 rc = VDGetOpenFlags(pDiskFrom, nImage, &uOpenFlagsFrom); 1683 if (VBOX_FAILURE(rc)) 1684 break; 1685 1686 /* Create destination image with the properties of the source image. */ 1687 /* @todo Copy the comment. */ 1688 if (enmTypeFrom == VD_IMAGE_TYPE_DIFF) 1689 { 1690 rc = VDCreateDiff(pDiskTo, pszBackend, pszFilename, uImageFlagsFrom, 1691 "", uOpenFlagsFrom, NULL, NULL); 1692 } else { 1693 rc = VDCreateBase(pDiskTo, pszBackend, pszFilename, enmTypeFrom, 1694 cbSize, uImageFlagsFrom, "", 1695 &PCHSGeometryFrom, &LCHSGeometryFrom, 1696 uOpenFlagsFrom, NULL, NULL); 1697 } 1698 if (VBOX_FAILURE(rc)) 1699 break; 1700 1701 pImageTo = pDiskTo->pLast; 1702 AssertBreak(VALID_PTR(pImageTo), rc = VERR_VDI_IMAGE_NOT_FOUND); 1703 1704 /* Allocate tmp buffer. */ 1705 pvBuf = RTMemTmpAlloc(VD_MERGE_BUFFER_SIZE); 1706 if (!pvBuf) 1707 { 1708 rc = VERR_NO_MEMORY; 1709 break; 1710 } 1711 1712 /* Copy the data. */ 1713 uint64_t uOffset = 0; 1714 uint64_t cbRemaining = cbSize; 1715 1716 do 1717 { 1718 size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining); 1719 1720 rc = vdReadHelper(pDiskFrom, pImageFrom, uOffset, pvBuf, 1721 cbThisRead); 1722 if (VBOX_FAILURE(rc)) 1723 break; 1724 1725 rc = vdWriteHelper(pDiskTo, pImageTo, uOffset, pvBuf, 1726 cbThisRead); 1727 if (VBOX_FAILURE(rc)) 1728 break; 1729 1730 uOffset += cbThisRead; 1731 cbRemaining -= cbThisRead; 1732 if (pfnProgress) 1733 { 1734 rc = pfnProgress(NULL /* WARNING! pVM=NULL */, 1735 ((cbSize - cbRemaining) * 100) / cbSize, 1736 pvUser); 1737 if (VBOX_FAILURE(rc)) 1738 break; 1739 } 1740 } while (uOffset < cbSize); 1741 1742 /* If fMoveByRename is set but the backend is different, close and delete pImageFrom. */ 1743 if ( (fMoveByRename == true) 1744 && (strcmp(pszBackend, pImageFrom->Backend->pszBackendName))) 1745 { 1746 vdRemoveImageFromList(pDiskFrom, pImageFrom); 1747 1748 /* Close and delete image. */ 1749 rc2 = pImageFrom->Backend->pfnClose(pImageFrom->pvBackendData, true); 1750 AssertRC(rc2); 1751 pImageFrom->pvBackendData = NULL; 1752 1753 /* Free remaining resources. */ 1754 if (pImageFrom->hPlugin != NIL_RTLDRMOD) 1755 RTLdrClose(pImageFrom->hPlugin); 1756 1757 if (pImageFrom->pszFilename) 1758 RTStrFree(pImageFrom->pszFilename); 1759 1760 RTMemFree(pImageFrom); 1761 } 1762 } while (0); 1763 1764 if (VBOX_FAILURE(rc) && pImageTo) 1765 { 1766 /* Error detected, but new image created. Remove image from list. */ 1767 vdRemoveImageFromList(pDiskTo, pImageTo); 1768 1769 /* Close and delete image. */ 1770 rc2 = pImageTo->Backend->pfnClose(pImageTo->pvBackendData, true); 1771 AssertRC(rc2); 1772 pImageTo->pvBackendData = NULL; 1773 1774 /* Free remaining resources. */ 1775 if (pImageTo->hPlugin != NIL_RTLDRMOD) 1776 RTLdrClose(pImageTo->hPlugin); 1777 1778 if (pImageTo->pszFilename) 1779 RTStrFree(pImageTo->pszFilename); 1780 1781 RTMemFree(pImageTo); 1782 } 1783 1784 if (pvBuf) 1785 RTMemTmpFree(pvBuf); 1786 1787 if (VBOX_SUCCESS(rc) && pfnProgress) 1788 pfnProgress(NULL /* WARNING! pVM=NULL */, 100, pvUser); 1789 1790 LogFlowFunc(("returns %Vrc\n", rc)); 1791 return rc; 1579 1792 } 1580 1793
Note:
See TracChangeset
for help on using the changeset viewer.