Changeset 31464 in vbox
- Timestamp:
- Aug 9, 2010 9:15:40 AM (15 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/settings.h
r31303 r31464 60 60 61 61 class ConfigFileError; 62 63 ////////////////////////////////////////////////////////////////////////////////64 //65 // Helper classes66 //67 ////////////////////////////////////////////////////////////////////////////////68 69 // ExtraDataItem (used by both VirtualBox.xml and machines XML)70 typedef std::map<com::Utf8Str, com::Utf8Str> ExtraDataItemsMap;71 struct USBDeviceFilter;72 typedef std::list<USBDeviceFilter> USBDeviceFiltersList;73 74 /**75 * Common base class for both MainConfigFile and MachineConfigFile76 * which contains some common logic for both.77 */78 class ConfigFileBase79 {80 public:81 bool fileExists();82 83 void copyBaseFrom(const ConfigFileBase &b);84 85 protected:86 ConfigFileBase(const com::Utf8Str *pstrFilename);87 ~ConfigFileBase();88 89 void parseUUID(com::Guid &guid,90 const com::Utf8Str &strUUID) const;91 void parseTimestamp(RTTIMESPEC ×tamp,92 const com::Utf8Str &str) const;93 94 com::Utf8Str makeString(const RTTIMESPEC &tm);95 96 void readExtraData(const xml::ElementNode &elmExtraData,97 ExtraDataItemsMap &map);98 void readUSBDeviceFilters(const xml::ElementNode &elmDeviceFilters,99 USBDeviceFiltersList &ll);100 101 void setVersionAttribute(xml::ElementNode &elm);102 void createStubDocument();103 104 void writeExtraData(xml::ElementNode &elmParent, const ExtraDataItemsMap &me);105 void writeUSBDeviceFilters(xml::ElementNode &elmParent,106 const USBDeviceFiltersList &ll,107 bool fHostMode);108 109 void clearDocument();110 111 struct Data;112 Data *m;113 114 private:115 // prohibit copying (Data contains pointers to XML which cannot be copied)116 ConfigFileBase(const ConfigFileBase&);117 118 friend class ConfigFileError;119 };120 62 121 63 //////////////////////////////////////////////////////////////////////////////// … … 157 99 }; 158 100 101 typedef std::map<com::Utf8Str, com::Utf8Str> PropertiesMap; 102 103 // ExtraDataItem (used by both VirtualBox.xml and machines XML) 104 typedef std::map<com::Utf8Str, com::Utf8Str> ExtraDataItemsMap; 105 struct USBDeviceFilter; 106 typedef std::list<USBDeviceFilter> USBDeviceFiltersList; 107 108 struct Medium; 109 typedef std::list<Medium> MediaList; 110 111 /** 112 * NOTE: If you add any fields in here, you must update a) the constructor and b) 113 * the operator== which is used by MachineConfigFile::operator==(), or otherwise 114 * your settings might never get saved. 115 */ 116 struct Medium 117 { 118 com::Guid uuid; 119 com::Utf8Str strLocation; 120 com::Utf8Str strDescription; 121 122 // the following are for hard disks only: 123 com::Utf8Str strFormat; 124 bool fAutoReset; // optional, only for diffs, default is false 125 PropertiesMap properties; 126 MediumType_T hdType; 127 128 MediaList llChildren; // only used with hard disks 129 130 bool operator==(const Medium &m) const; 131 }; 132 133 /** 134 * NOTE: If you add any fields in here, you must update a) the constructor and b) 135 * the operator== which is used by MachineConfigFile::operator==(), or otherwise 136 * your settings might never get saved. 137 */ 138 struct MediaRegistry 139 { 140 MediaList llHardDisks, 141 llDvdImages, 142 llFloppyImages; 143 144 bool operator==(const MediaRegistry &m) const; 145 }; 146 147 /** 148 * Common base class for both MainConfigFile and MachineConfigFile 149 * which contains some common logic for both. 150 */ 151 class ConfigFileBase 152 { 153 public: 154 bool fileExists(); 155 156 void copyBaseFrom(const ConfigFileBase &b); 157 158 protected: 159 ConfigFileBase(const com::Utf8Str *pstrFilename); 160 ~ConfigFileBase(); 161 162 void parseUUID(com::Guid &guid, 163 const com::Utf8Str &strUUID) const; 164 void parseTimestamp(RTTIMESPEC ×tamp, 165 const com::Utf8Str &str) const; 166 167 com::Utf8Str makeString(const RTTIMESPEC &tm); 168 169 void readExtraData(const xml::ElementNode &elmExtraData, 170 ExtraDataItemsMap &map); 171 void readUSBDeviceFilters(const xml::ElementNode &elmDeviceFilters, 172 USBDeviceFiltersList &ll); 173 typedef enum {Error, HardDisk, DVDImage, FloppyImage} MediaType; 174 void readMedium(MediaType t, const xml::ElementNode &elmMedium, MediaList &llMedia); 175 void readMediaRegistry(const xml::ElementNode &elmMediaRegistry, MediaRegistry &mr); 176 177 void setVersionAttribute(xml::ElementNode &elm); 178 void createStubDocument(); 179 180 void buildExtraData(xml::ElementNode &elmParent, const ExtraDataItemsMap &me); 181 void buildUSBDeviceFilters(xml::ElementNode &elmParent, 182 const USBDeviceFiltersList &ll, 183 bool fHostMode); 184 void buildHardDisk(xml::ElementNode &elmMedium, 185 const Medium &m, 186 uint32_t level); 187 void buildMediaRegistry(xml::ElementNode &elmParent, 188 const MediaRegistry &mr); 189 void clearDocument(); 190 191 struct Data; 192 Data *m; 193 194 private: 195 // prohibit copying (Data contains pointers to XML which cannot be copied) 196 ConfigFileBase(const ConfigFileBase&); 197 198 friend class ConfigFileError; 199 }; 200 159 201 //////////////////////////////////////////////////////////////////////////////// 160 202 // … … 182 224 }; 183 225 184 typedef std::map<com::Utf8Str, com::Utf8Str> PropertiesMap;185 186 struct Medium;187 typedef std::list<Medium> MediaList;188 189 struct Medium190 {191 com::Guid uuid;192 com::Utf8Str strLocation;193 com::Utf8Str strDescription;194 195 // the following are for hard disks only:196 com::Utf8Str strFormat;197 bool fAutoReset; // optional, only for diffs, default is false198 PropertiesMap properties;199 MediumType_T hdType;200 201 MediaList llChildren; // only used with hard disks202 };203 204 226 struct MachineRegistryEntry 205 227 { … … 225 247 MainConfigFile(const com::Utf8Str *pstrFilename); 226 248 227 typedef enum {Error, HardDisk, DVDImage, FloppyImage} MediaType;228 void readMedium(MediaType t, const xml::ElementNode &elmMedium, MediaList &llMedia);229 void readMediaRegistry(const xml::ElementNode &elmMediaRegistry);230 249 void readMachineRegistry(const xml::ElementNode &elmMachineRegistry); 231 250 void readDHCPServers(const xml::ElementNode &elmDHCPServers); 232 251 233 void writeHardDisk(xml::ElementNode &elmMedium,234 const Medium &m,235 uint32_t level);236 252 void write(const com::Utf8Str strFilename); 237 253 238 254 Host host; 239 255 SystemProperties systemProperties; 240 MediaList llHardDisks, 241 llDvdImages, 242 llFloppyImages; 256 MediaRegistry mediaRegistry; 243 257 MachinesRegistry llMachines; 244 258 DHCPServersList llDhcpServers; … … 865 879 Hardware hardwareMachine; 866 880 Storage storageMachine; 881 MediaRegistry mediaRegistry; 867 882 868 883 ExtraDataItemsMap mapExtraDataItems; … … 882 897 BuildMachineXML_IncludeSnapshots = 0x01, 883 898 BuildMachineXML_WriteVboxVersionAttribute = 0x02, 884 BuildMachineXML_SkipRemovableMedia = 0x02 899 BuildMachineXML_SkipRemovableMedia = 0x04, 900 BuildMachineXML_MediaRegistry = 0x08 885 901 }; 886 902 void buildMachineXML(xml::ElementNode &elmMachine, -
trunk/src/VBox/Main/ApplianceImplExport.cpp
r30764 r31464 1301 1301 settings::MachineConfigFile::BuildMachineXML_WriteVboxVersionAttribute 1302 1302 | settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia, 1303 // but not BuildMachineXML_IncludeSnapshots 1303 // but not BuildMachineXML_IncludeSnapshots nor BuildMachineXML_MediaRegistry 1304 1304 pllElementsWithUuidAttributes); 1305 1305 delete pConfig; -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r31388 r31464 599 599 HRESULT rc = S_OK; 600 600 settings::MediaList::const_iterator it; 601 for (it = m->pMainConfigFile-> llHardDisks.begin();602 it != m->pMainConfigFile-> llHardDisks.end();601 for (it = m->pMainConfigFile->mediaRegistry.llHardDisks.begin(); 602 it != m->pMainConfigFile->mediaRegistry.llHardDisks.end(); 603 603 ++it) 604 604 { … … 617 617 } 618 618 619 for (it = m->pMainConfigFile-> llDvdImages.begin();620 it != m->pMainConfigFile-> llDvdImages.end();619 for (it = m->pMainConfigFile->mediaRegistry.llDvdImages.begin(); 620 it != m->pMainConfigFile->mediaRegistry.llDvdImages.end(); 621 621 ++it) 622 622 { … … 632 632 } 633 633 634 for (it = m->pMainConfigFile-> llFloppyImages.begin();635 it != m->pMainConfigFile-> llFloppyImages.end();634 for (it = m->pMainConfigFile->mediaRegistry.llFloppyImages.begin(); 635 it != m->pMainConfigFile->mediaRegistry.llFloppyImages.end(); 636 636 ++it) 637 637 { … … 3290 3290 /* now copy the temp data to the config file under the VirtualBox lock */ 3291 3291 m->pMainConfigFile->llMachines = machinesTemp; 3292 m->pMainConfigFile-> llHardDisks = hardDisksTemp;3293 m->pMainConfigFile-> llDvdImages = dvdsTemp;3294 m->pMainConfigFile-> llFloppyImages = floppiesTemp;3292 m->pMainConfigFile->mediaRegistry.llHardDisks = hardDisksTemp; 3293 m->pMainConfigFile->mediaRegistry.llDvdImages = dvdsTemp; 3294 m->pMainConfigFile->mediaRegistry.llFloppyImages = floppiesTemp; 3295 3295 m->pMainConfigFile->llDhcpServers = dhcpServersTemp; 3296 3296 -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r31334 r31464 468 468 <const name="v1_11" value="13"> 469 469 <desc>Settings version "1.11", written by VirtualBox 3.3.x.</desc> 470 <!-- Machine changes: HD Audio controller 470 <!-- Machine changes: HD Audio controller, per-machine disk registries 471 471 --> 472 472 </const> -
trunk/src/VBox/Main/xml/Settings.cpp
r31301 r31464 208 208 //////////////////////////////////////////////////////////////////////////////// 209 209 // 210 // MediaRegistry 211 // 212 //////////////////////////////////////////////////////////////////////////////// 213 214 bool Medium::operator==(const Medium &m) const 215 { 216 return (uuid == m.uuid) 217 && (strLocation == m.strLocation) 218 && (strDescription == m.strDescription) 219 && (strFormat == m.strFormat) 220 && (fAutoReset == m.fAutoReset) 221 && (properties == m.properties) 222 && (hdType == m.hdType) 223 && (llChildren== m.llChildren); // this is deep and recurses 224 } 225 226 bool MediaRegistry::operator==(const MediaRegistry &m) const 227 { 228 return llHardDisks == m.llHardDisks 229 && llDvdImages == m.llDvdImages 230 && llFloppyImages == m.llFloppyImages; 231 } 232 233 //////////////////////////////////////////////////////////////////////////////// 234 // 210 235 // ConfigFileBase 211 236 // … … 526 551 527 552 /** 528 * Adds a "version" attribute to the given XML element with the529 * VirtualBox settings version (e.g. "1.10-linux"). Used by530 * the XML format for the root element and by the OVF export531 * for the vbox:Machine element.532 * @param elm533 */534 void ConfigFileBase::setVersionAttribute(xml::ElementNode &elm)535 {536 const char *pcszVersion = NULL;537 switch (m->sv)538 {539 case SettingsVersion_v1_8:540 pcszVersion = "1.8";541 break;542 543 case SettingsVersion_v1_9:544 pcszVersion = "1.9";545 break;546 547 case SettingsVersion_v1_10:548 pcszVersion = "1.10";549 break;550 551 case SettingsVersion_v1_11:552 pcszVersion = "1.11";553 break;554 555 case SettingsVersion_Future:556 // can be set if this code runs on XML files that were created by a future version of VBox;557 // in that case, downgrade to current version when writing since we can't write future versions...558 pcszVersion = "1.11";559 m->sv = SettingsVersion_v1_10;560 break;561 562 default:563 // silently upgrade if this is less than 1.7 because that's the oldest we can write564 pcszVersion = "1.7";565 m->sv = SettingsVersion_v1_7;566 break;567 }568 569 elm.setAttribute("version", Utf8StrFmt("%s-%s",570 pcszVersion,571 VBOX_XML_PLATFORM)); // e.g. "linux"572 }573 574 /**575 * Creates a new stub xml::Document in the m->pDoc member with the576 * root "VirtualBox" element set up. This is used by both577 * MainConfigFile and MachineConfigFile at the beginning of writing578 * out their XML.579 *580 * Before calling this, it is the responsibility of the caller to581 * set the "sv" member to the required settings version that is to582 * be written. For newly created files, the settings version will be583 * the latest (1.11); for files read in from disk earlier, it will be584 * the settings version indicated in the file. However, this method585 * will silently make sure that the settings version is always586 * at least 1.7 and change it if necessary, since there is no write587 * support for earlier settings versions.588 */589 void ConfigFileBase::createStubDocument()590 {591 Assert(m->pDoc == NULL);592 m->pDoc = new xml::Document;593 594 m->pelmRoot = m->pDoc->createRootElement("VirtualBox");595 m->pelmRoot->setAttribute("xmlns", VBOX_XML_NAMESPACE);596 597 // add settings version attribute to root element598 setVersionAttribute(*m->pelmRoot);599 600 // since this gets called before the XML document is actually written out,601 // this is where we must check whether we're upgrading the settings version602 // and need to make a backup, so the user can go back to an earlier603 // VirtualBox version and recover his old settings files.604 if ( (m->svRead != SettingsVersion_Null) // old file exists?605 && (m->svRead < m->sv) // we're upgrading?606 )607 {608 // compose new filename: strip off trailing ".xml"609 Utf8Str strFilenameNew = m->strFilename.substr(0, m->strFilename.length() - 4);610 // and append something likd "-1.3-linux.xml"611 strFilenameNew.append("-");612 strFilenameNew.append(m->strSettingsVersionFull); // e.g. "1.3-linux"613 strFilenameNew.append(".xml");614 615 RTFileMove(m->strFilename.c_str(),616 strFilenameNew.c_str(),617 0); // no RTFILEMOVE_FLAGS_REPLACE618 619 // do this only once620 m->svRead = SettingsVersion_Null;621 }622 }623 624 /**625 * Creates an <ExtraData> node under the given parent element with626 * <ExtraDataItem> childern according to the contents of the given627 * map.628 * This is in ConfigFileBase because it's used in both MainConfigFile629 * MachineConfigFile, which both can have extradata.630 *631 * @param elmParent632 * @param me633 */634 void ConfigFileBase::writeExtraData(xml::ElementNode &elmParent,635 const ExtraDataItemsMap &me)636 {637 if (me.size())638 {639 xml::ElementNode *pelmExtraData = elmParent.createChild("ExtraData");640 for (ExtraDataItemsMap::const_iterator it = me.begin();641 it != me.end();642 ++it)643 {644 const Utf8Str &strName = it->first;645 const Utf8Str &strValue = it->second;646 xml::ElementNode *pelmThis = pelmExtraData->createChild("ExtraDataItem");647 pelmThis->setAttribute("name", strName);648 pelmThis->setAttribute("value", strValue);649 }650 }651 }652 653 /**654 * Creates <DeviceFilter> nodes under the given parent element according to655 * the contents of the given USBDeviceFiltersList. This is in ConfigFileBase656 * because it's used in both MainConfigFile (for host filters) and657 * MachineConfigFile (for machine filters).658 *659 * If fHostMode is true, this means that we're supposed to write filters660 * for the IHost interface (respect "action", omit "strRemote" and661 * "ulMaskedInterfaces" in struct USBDeviceFilter).662 *663 * @param elmParent664 * @param ll665 * @param fHostMode666 */667 void ConfigFileBase::writeUSBDeviceFilters(xml::ElementNode &elmParent,668 const USBDeviceFiltersList &ll,669 bool fHostMode)670 {671 for (USBDeviceFiltersList::const_iterator it = ll.begin();672 it != ll.end();673 ++it)674 {675 const USBDeviceFilter &flt = *it;676 xml::ElementNode *pelmFilter = elmParent.createChild("DeviceFilter");677 pelmFilter->setAttribute("name", flt.strName);678 pelmFilter->setAttribute("active", flt.fActive);679 if (flt.strVendorId.length())680 pelmFilter->setAttribute("vendorId", flt.strVendorId);681 if (flt.strProductId.length())682 pelmFilter->setAttribute("productId", flt.strProductId);683 if (flt.strRevision.length())684 pelmFilter->setAttribute("revision", flt.strRevision);685 if (flt.strManufacturer.length())686 pelmFilter->setAttribute("manufacturer", flt.strManufacturer);687 if (flt.strProduct.length())688 pelmFilter->setAttribute("product", flt.strProduct);689 if (flt.strSerialNumber.length())690 pelmFilter->setAttribute("serialNumber", flt.strSerialNumber);691 if (flt.strPort.length())692 pelmFilter->setAttribute("port", flt.strPort);693 694 if (fHostMode)695 {696 const char *pcsz =697 (flt.action == USBDeviceFilterAction_Ignore) ? "Ignore"698 : /*(flt.action == USBDeviceFilterAction_Hold) ?*/ "Hold";699 pelmFilter->setAttribute("action", pcsz);700 }701 else702 {703 if (flt.strRemote.length())704 pelmFilter->setAttribute("remote", flt.strRemote);705 if (flt.ulMaskedInterfaces)706 pelmFilter->setAttribute("maskedInterfaces", flt.ulMaskedInterfaces);707 }708 }709 }710 711 /**712 * Cleans up memory allocated by the internal XML parser. To be called by713 * descendant classes when they're done analyzing the DOM tree to discard it.714 */715 void ConfigFileBase::clearDocument()716 {717 m->cleanup();718 }719 720 /**721 * Returns true only if the underlying config file exists on disk;722 * either because the file has been loaded from disk, or it's been written723 * to disk, or both.724 * @return725 */726 bool ConfigFileBase::fileExists()727 {728 return m->fFileExists;729 }730 731 /**732 * Copies the base variables from another instance. Used by Machine::saveSettings733 * so that the settings version does not get lost when a copy of the Machine settings734 * file is made to see if settings have actually changed.735 * @param b736 */737 void ConfigFileBase::copyBaseFrom(const ConfigFileBase &b)738 {739 m->copyFrom(*b.m);740 }741 742 ////////////////////////////////////////////////////////////////////////////////743 //744 // Structures shared between Machine XML and VirtualBox.xml745 //746 ////////////////////////////////////////////////////////////////////////////////747 748 /**749 * Comparison operator. This gets called from MachineConfigFile::operator==,750 * which in turn gets called from Machine::saveSettings to figure out whether751 * machine settings have really changed and thus need to be written out to disk.752 */753 bool USBDeviceFilter::operator==(const USBDeviceFilter &u) const754 {755 return ( (this == &u)756 || ( (strName == u.strName)757 && (fActive == u.fActive)758 && (strVendorId == u.strVendorId)759 && (strProductId == u.strProductId)760 && (strRevision == u.strRevision)761 && (strManufacturer == u.strManufacturer)762 && (strProduct == u.strProduct)763 && (strSerialNumber == u.strSerialNumber)764 && (strPort == u.strPort)765 && (action == u.action)766 && (strRemote == u.strRemote)767 && (ulMaskedInterfaces == u.ulMaskedInterfaces)768 )769 );770 }771 772 ////////////////////////////////////////////////////////////////////////////////773 //774 // MainConfigFile775 //776 ////////////////////////////////////////////////////////////////////////////////777 778 /**779 * Reads one <MachineEntry> from the main VirtualBox.xml file.780 * @param elmMachineRegistry781 */782 void MainConfigFile::readMachineRegistry(const xml::ElementNode &elmMachineRegistry)783 {784 // <MachineEntry uuid="{ xxx }" src=" xxx "/>785 xml::NodesLoop nl1(elmMachineRegistry);786 const xml::ElementNode *pelmChild1;787 while ((pelmChild1 = nl1.forAllNodes()))788 {789 if (pelmChild1->nameEquals("MachineEntry"))790 {791 MachineRegistryEntry mre;792 Utf8Str strUUID;793 if ( ((pelmChild1->getAttributeValue("uuid", strUUID)))794 && ((pelmChild1->getAttributeValue("src", mre.strSettingsFile)))795 )796 {797 parseUUID(mre.uuid, strUUID);798 llMachines.push_back(mre);799 }800 else801 throw ConfigFileError(this, pelmChild1, N_("Required MachineEntry/@uuid or @src attribute is missing"));802 }803 }804 }805 806 /**807 553 * Reads a media registry entry from the main VirtualBox.xml file. 808 554 * … … 816 562 * @param llMedia 817 563 */ 818 void MainConfigFile::readMedium(MediaType t,564 void ConfigFileBase::readMedium(MediaType t, 819 565 const xml::ElementNode &elmMedium, // HardDisk node if root; if recursing, 820 566 // child HardDisk node or DiffHardDisk node for pre-1.4 … … 986 732 987 733 /** 988 * Reads in the entire <MediaRegistry> chunk. For pre-1.4 files, this gets called 989 * with the <DiskRegistry> chunk instead. 734 * Reads in the entire <MediaRegistry> chunk and stores its media in the lists 735 * of the given MediaRegistry structure. 736 * 737 * This is used in both MainConfigFile and MachineConfigFile since starting with 738 * VirtualBox 3.3, we can have media registries in both. 739 * 740 * For pre-1.4 files, this gets called with the <DiskRegistry> chunk instead. 741 * 990 742 * @param elmMediaRegistry 991 743 */ 992 void MainConfigFile::readMediaRegistry(const xml::ElementNode &elmMediaRegistry) 744 void ConfigFileBase::readMediaRegistry(const xml::ElementNode &elmMediaRegistry, 745 MediaRegistry &mr) 993 746 { 994 747 xml::NodesLoop nl1(elmMediaRegistry); … … 1015 768 readMedium(t, 1016 769 *pelmMedium, 1017 llHardDisks); // list to append hard disk data to: the root list770 mr.llHardDisks); // list to append hard disk data to: the root list 1018 771 else if ( t == DVDImage 1019 772 && (pelmMedium->nameEquals("Image")) … … 1021 774 readMedium(t, 1022 775 *pelmMedium, 1023 llDvdImages); // list to append dvd images to: the root list776 mr.llDvdImages); // list to append dvd images to: the root list 1024 777 else if ( t == FloppyImage 1025 778 && (pelmMedium->nameEquals("Image")) … … 1027 780 readMedium(t, 1028 781 *pelmMedium, 1029 llFloppyImages); // list to append floppy images to: the root list 782 mr.llFloppyImages); // list to append floppy images to: the root list 783 } 784 } 785 } 786 787 /** 788 * Adds a "version" attribute to the given XML element with the 789 * VirtualBox settings version (e.g. "1.10-linux"). Used by 790 * the XML format for the root element and by the OVF export 791 * for the vbox:Machine element. 792 * @param elm 793 */ 794 void ConfigFileBase::setVersionAttribute(xml::ElementNode &elm) 795 { 796 const char *pcszVersion = NULL; 797 switch (m->sv) 798 { 799 case SettingsVersion_v1_8: 800 pcszVersion = "1.8"; 801 break; 802 803 case SettingsVersion_v1_9: 804 pcszVersion = "1.9"; 805 break; 806 807 case SettingsVersion_v1_10: 808 pcszVersion = "1.10"; 809 break; 810 811 case SettingsVersion_v1_11: 812 pcszVersion = "1.11"; 813 break; 814 815 case SettingsVersion_Future: 816 // can be set if this code runs on XML files that were created by a future version of VBox; 817 // in that case, downgrade to current version when writing since we can't write future versions... 818 pcszVersion = "1.11"; 819 m->sv = SettingsVersion_v1_10; 820 break; 821 822 default: 823 // silently upgrade if this is less than 1.7 because that's the oldest we can write 824 pcszVersion = "1.7"; 825 m->sv = SettingsVersion_v1_7; 826 break; 827 } 828 829 elm.setAttribute("version", Utf8StrFmt("%s-%s", 830 pcszVersion, 831 VBOX_XML_PLATFORM)); // e.g. "linux" 832 } 833 834 /** 835 * Creates a new stub xml::Document in the m->pDoc member with the 836 * root "VirtualBox" element set up. This is used by both 837 * MainConfigFile and MachineConfigFile at the beginning of writing 838 * out their XML. 839 * 840 * Before calling this, it is the responsibility of the caller to 841 * set the "sv" member to the required settings version that is to 842 * be written. For newly created files, the settings version will be 843 * the latest (1.11); for files read in from disk earlier, it will be 844 * the settings version indicated in the file. However, this method 845 * will silently make sure that the settings version is always 846 * at least 1.7 and change it if necessary, since there is no write 847 * support for earlier settings versions. 848 */ 849 void ConfigFileBase::createStubDocument() 850 { 851 Assert(m->pDoc == NULL); 852 m->pDoc = new xml::Document; 853 854 m->pelmRoot = m->pDoc->createRootElement("VirtualBox"); 855 m->pelmRoot->setAttribute("xmlns", VBOX_XML_NAMESPACE); 856 857 // add settings version attribute to root element 858 setVersionAttribute(*m->pelmRoot); 859 860 // since this gets called before the XML document is actually written out, 861 // this is where we must check whether we're upgrading the settings version 862 // and need to make a backup, so the user can go back to an earlier 863 // VirtualBox version and recover his old settings files. 864 if ( (m->svRead != SettingsVersion_Null) // old file exists? 865 && (m->svRead < m->sv) // we're upgrading? 866 ) 867 { 868 // compose new filename: strip off trailing ".xml" 869 Utf8Str strFilenameNew = m->strFilename.substr(0, m->strFilename.length() - 4); 870 // and append something likd "-1.3-linux.xml" 871 strFilenameNew.append("-"); 872 strFilenameNew.append(m->strSettingsVersionFull); // e.g. "1.3-linux" 873 strFilenameNew.append(".xml"); 874 875 RTFileMove(m->strFilename.c_str(), 876 strFilenameNew.c_str(), 877 0); // no RTFILEMOVE_FLAGS_REPLACE 878 879 // do this only once 880 m->svRead = SettingsVersion_Null; 881 } 882 } 883 884 /** 885 * Creates an <ExtraData> node under the given parent element with 886 * <ExtraDataItem> childern according to the contents of the given 887 * map. 888 * 889 * This is in ConfigFileBase because it's used in both MainConfigFile 890 * and MachineConfigFile, which both can have extradata. 891 * 892 * @param elmParent 893 * @param me 894 */ 895 void ConfigFileBase::buildExtraData(xml::ElementNode &elmParent, 896 const ExtraDataItemsMap &me) 897 { 898 if (me.size()) 899 { 900 xml::ElementNode *pelmExtraData = elmParent.createChild("ExtraData"); 901 for (ExtraDataItemsMap::const_iterator it = me.begin(); 902 it != me.end(); 903 ++it) 904 { 905 const Utf8Str &strName = it->first; 906 const Utf8Str &strValue = it->second; 907 xml::ElementNode *pelmThis = pelmExtraData->createChild("ExtraDataItem"); 908 pelmThis->setAttribute("name", strName); 909 pelmThis->setAttribute("value", strValue); 910 } 911 } 912 } 913 914 /** 915 * Creates <DeviceFilter> nodes under the given parent element according to 916 * the contents of the given USBDeviceFiltersList. This is in ConfigFileBase 917 * because it's used in both MainConfigFile (for host filters) and 918 * MachineConfigFile (for machine filters). 919 * 920 * If fHostMode is true, this means that we're supposed to write filters 921 * for the IHost interface (respect "action", omit "strRemote" and 922 * "ulMaskedInterfaces" in struct USBDeviceFilter). 923 * 924 * @param elmParent 925 * @param ll 926 * @param fHostMode 927 */ 928 void ConfigFileBase::buildUSBDeviceFilters(xml::ElementNode &elmParent, 929 const USBDeviceFiltersList &ll, 930 bool fHostMode) 931 { 932 for (USBDeviceFiltersList::const_iterator it = ll.begin(); 933 it != ll.end(); 934 ++it) 935 { 936 const USBDeviceFilter &flt = *it; 937 xml::ElementNode *pelmFilter = elmParent.createChild("DeviceFilter"); 938 pelmFilter->setAttribute("name", flt.strName); 939 pelmFilter->setAttribute("active", flt.fActive); 940 if (flt.strVendorId.length()) 941 pelmFilter->setAttribute("vendorId", flt.strVendorId); 942 if (flt.strProductId.length()) 943 pelmFilter->setAttribute("productId", flt.strProductId); 944 if (flt.strRevision.length()) 945 pelmFilter->setAttribute("revision", flt.strRevision); 946 if (flt.strManufacturer.length()) 947 pelmFilter->setAttribute("manufacturer", flt.strManufacturer); 948 if (flt.strProduct.length()) 949 pelmFilter->setAttribute("product", flt.strProduct); 950 if (flt.strSerialNumber.length()) 951 pelmFilter->setAttribute("serialNumber", flt.strSerialNumber); 952 if (flt.strPort.length()) 953 pelmFilter->setAttribute("port", flt.strPort); 954 955 if (fHostMode) 956 { 957 const char *pcsz = 958 (flt.action == USBDeviceFilterAction_Ignore) ? "Ignore" 959 : /*(flt.action == USBDeviceFilterAction_Hold) ?*/ "Hold"; 960 pelmFilter->setAttribute("action", pcsz); 961 } 962 else 963 { 964 if (flt.strRemote.length()) 965 pelmFilter->setAttribute("remote", flt.strRemote); 966 if (flt.ulMaskedInterfaces) 967 pelmFilter->setAttribute("maskedInterfaces", flt.ulMaskedInterfaces); 968 } 969 } 970 } 971 972 /** 973 * Creates a single <HardDisk> element for the given Medium structure 974 * and recurses to write the child hard disks underneath. Called from 975 * MainConfigFile::write(). 976 * 977 * @param elmMedium 978 * @param m 979 * @param level 980 */ 981 void ConfigFileBase::buildHardDisk(xml::ElementNode &elmMedium, 982 const Medium &mdm, 983 uint32_t level) // 0 for "root" call, incremented with each recursion 984 { 985 xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk"); 986 pelmHardDisk->setAttribute("uuid", mdm.uuid.toStringCurly()); 987 pelmHardDisk->setAttribute("location", mdm.strLocation); 988 pelmHardDisk->setAttribute("format", mdm.strFormat); 989 if (mdm.fAutoReset) 990 pelmHardDisk->setAttribute("autoReset", mdm.fAutoReset); 991 if (mdm.strDescription.length()) 992 pelmHardDisk->setAttribute("Description", mdm.strDescription); 993 994 for (PropertiesMap::const_iterator it = mdm.properties.begin(); 995 it != mdm.properties.end(); 996 ++it) 997 { 998 xml::ElementNode *pelmProp = pelmHardDisk->createChild("Property"); 999 pelmProp->setAttribute("name", it->first); 1000 pelmProp->setAttribute("value", it->second); 1001 } 1002 1003 // only for base hard disks, save the type 1004 if (level == 0) 1005 { 1006 const char *pcszType = 1007 mdm.hdType == MediumType_Normal ? "Normal" : 1008 mdm.hdType == MediumType_Immutable ? "Immutable" : 1009 mdm.hdType == MediumType_Writethrough ? "Writethrough" : 1010 mdm.hdType == MediumType_Shareable ? "Shareable" : "INVALID"; 1011 pelmHardDisk->setAttribute("type", pcszType); 1012 } 1013 1014 for (MediaList::const_iterator it = mdm.llChildren.begin(); 1015 it != mdm.llChildren.end(); 1016 ++it) 1017 { 1018 // recurse for children 1019 buildHardDisk(*pelmHardDisk, // parent 1020 *it, // settings::Medium 1021 ++level); // recursion level 1022 } 1023 } 1024 1025 /** 1026 * Creates a <MediaRegistry> node under the given parent and writes out all 1027 * hard disks and DVD and floppy images from the lists in the given MediaRegistry 1028 * structure under it. 1029 * 1030 * This is used in both MainConfigFile and MachineConfigFile since starting with 1031 * VirtualBox 3.3, we can have media registries in both. 1032 * 1033 * @param elmParent 1034 * @param mr 1035 */ 1036 void ConfigFileBase::buildMediaRegistry(xml::ElementNode &elmParent, 1037 const MediaRegistry &mr) 1038 { 1039 xml::ElementNode *pelmMediaRegistry = elmParent.createChild("MediaRegistry"); 1040 1041 xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks"); 1042 for (MediaList::const_iterator it = mr.llHardDisks.begin(); 1043 it != mr.llHardDisks.end(); 1044 ++it) 1045 { 1046 buildHardDisk(*pelmHardDisks, *it, 0); 1047 } 1048 1049 xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages"); 1050 for (MediaList::const_iterator it = mr.llDvdImages.begin(); 1051 it != mr.llDvdImages.end(); 1052 ++it) 1053 { 1054 const Medium &mdm = *it; 1055 xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image"); 1056 pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly()); 1057 pelmMedium->setAttribute("location", mdm.strLocation); 1058 if (mdm.strDescription.length()) 1059 pelmMedium->setAttribute("Description", mdm.strDescription); 1060 } 1061 1062 xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages"); 1063 for (MediaList::const_iterator it = mr.llFloppyImages.begin(); 1064 it != mr.llFloppyImages.end(); 1065 ++it) 1066 { 1067 const Medium &mdm = *it; 1068 xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image"); 1069 pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly()); 1070 pelmMedium->setAttribute("location", mdm.strLocation); 1071 if (mdm.strDescription.length()) 1072 pelmMedium->setAttribute("Description", mdm.strDescription); 1073 } 1074 } 1075 1076 /** 1077 * Cleans up memory allocated by the internal XML parser. To be called by 1078 * descendant classes when they're done analyzing the DOM tree to discard it. 1079 */ 1080 void ConfigFileBase::clearDocument() 1081 { 1082 m->cleanup(); 1083 } 1084 1085 /** 1086 * Returns true only if the underlying config file exists on disk; 1087 * either because the file has been loaded from disk, or it's been written 1088 * to disk, or both. 1089 * @return 1090 */ 1091 bool ConfigFileBase::fileExists() 1092 { 1093 return m->fFileExists; 1094 } 1095 1096 /** 1097 * Copies the base variables from another instance. Used by Machine::saveSettings 1098 * so that the settings version does not get lost when a copy of the Machine settings 1099 * file is made to see if settings have actually changed. 1100 * @param b 1101 */ 1102 void ConfigFileBase::copyBaseFrom(const ConfigFileBase &b) 1103 { 1104 m->copyFrom(*b.m); 1105 } 1106 1107 //////////////////////////////////////////////////////////////////////////////// 1108 // 1109 // Structures shared between Machine XML and VirtualBox.xml 1110 // 1111 //////////////////////////////////////////////////////////////////////////////// 1112 1113 /** 1114 * Comparison operator. This gets called from MachineConfigFile::operator==, 1115 * which in turn gets called from Machine::saveSettings to figure out whether 1116 * machine settings have really changed and thus need to be written out to disk. 1117 */ 1118 bool USBDeviceFilter::operator==(const USBDeviceFilter &u) const 1119 { 1120 return ( (this == &u) 1121 || ( (strName == u.strName) 1122 && (fActive == u.fActive) 1123 && (strVendorId == u.strVendorId) 1124 && (strProductId == u.strProductId) 1125 && (strRevision == u.strRevision) 1126 && (strManufacturer == u.strManufacturer) 1127 && (strProduct == u.strProduct) 1128 && (strSerialNumber == u.strSerialNumber) 1129 && (strPort == u.strPort) 1130 && (action == u.action) 1131 && (strRemote == u.strRemote) 1132 && (ulMaskedInterfaces == u.ulMaskedInterfaces) 1133 ) 1134 ); 1135 } 1136 1137 //////////////////////////////////////////////////////////////////////////////// 1138 // 1139 // MainConfigFile 1140 // 1141 //////////////////////////////////////////////////////////////////////////////// 1142 1143 /** 1144 * Reads one <MachineEntry> from the main VirtualBox.xml file. 1145 * @param elmMachineRegistry 1146 */ 1147 void MainConfigFile::readMachineRegistry(const xml::ElementNode &elmMachineRegistry) 1148 { 1149 // <MachineEntry uuid="{ xxx }" src=" xxx "/> 1150 xml::NodesLoop nl1(elmMachineRegistry); 1151 const xml::ElementNode *pelmChild1; 1152 while ((pelmChild1 = nl1.forAllNodes())) 1153 { 1154 if (pelmChild1->nameEquals("MachineEntry")) 1155 { 1156 MachineRegistryEntry mre; 1157 Utf8Str strUUID; 1158 if ( ((pelmChild1->getAttributeValue("uuid", strUUID))) 1159 && ((pelmChild1->getAttributeValue("src", mre.strSettingsFile))) 1160 ) 1161 { 1162 parseUUID(mre.uuid, strUUID); 1163 llMachines.push_back(mre); 1164 } 1165 else 1166 throw ConfigFileError(this, pelmChild1, N_("Required MachineEntry/@uuid or @src attribute is missing")); 1030 1167 } 1031 1168 } … … 1109 1246 ) 1110 1247 ) 1111 readMediaRegistry(*pelmGlobalChild );1248 readMediaRegistry(*pelmGlobalChild, mediaRegistry); 1112 1249 else if (pelmGlobalChild->nameEquals("NetserviceRegistry")) 1113 1250 { … … 1155 1292 1156 1293 /** 1157 * Creates a single <HardDisk> element for the given Medium structure1158 * and recurses to write the child hard disks underneath. Called from1159 * MainConfigFile::write().1160 *1161 * @param elmMedium1162 * @param m1163 * @param level1164 */1165 void MainConfigFile::writeHardDisk(xml::ElementNode &elmMedium,1166 const Medium &mdm,1167 uint32_t level) // 0 for "root" call, incremented with each recursion1168 {1169 xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk");1170 pelmHardDisk->setAttribute("uuid", mdm.uuid.toStringCurly());1171 pelmHardDisk->setAttribute("location", mdm.strLocation);1172 pelmHardDisk->setAttribute("format", mdm.strFormat);1173 if (mdm.fAutoReset)1174 pelmHardDisk->setAttribute("autoReset", mdm.fAutoReset);1175 if (mdm.strDescription.length())1176 pelmHardDisk->setAttribute("Description", mdm.strDescription);1177 1178 for (PropertiesMap::const_iterator it = mdm.properties.begin();1179 it != mdm.properties.end();1180 ++it)1181 {1182 xml::ElementNode *pelmProp = pelmHardDisk->createChild("Property");1183 pelmProp->setAttribute("name", it->first);1184 pelmProp->setAttribute("value", it->second);1185 }1186 1187 // only for base hard disks, save the type1188 if (level == 0)1189 {1190 const char *pcszType =1191 mdm.hdType == MediumType_Normal ? "Normal" :1192 mdm.hdType == MediumType_Immutable ? "Immutable" :1193 mdm.hdType == MediumType_Writethrough ? "Writethrough" :1194 mdm.hdType == MediumType_Shareable ? "Shareable" : "INVALID";1195 pelmHardDisk->setAttribute("type", pcszType);1196 }1197 1198 for (MediaList::const_iterator it = mdm.llChildren.begin();1199 it != mdm.llChildren.end();1200 ++it)1201 {1202 // recurse for children1203 writeHardDisk(*pelmHardDisk, // parent1204 *it, // settings::Medium1205 ++level); // recursion level1206 }1207 }1208 1209 /**1210 1294 * Called from the IVirtualBox interface to write out VirtualBox.xml. This 1211 1295 * builds an XML DOM tree and writes it out to disk. … … 1218 1302 xml::ElementNode *pelmGlobal = m->pelmRoot->createChild("Global"); 1219 1303 1220 writeExtraData(*pelmGlobal, mapExtraDataItems);1304 buildExtraData(*pelmGlobal, mapExtraDataItems); 1221 1305 1222 1306 xml::ElementNode *pelmMachineRegistry = pelmGlobal->createChild("MachineRegistry"); … … 1232 1316 } 1233 1317 1234 xml::ElementNode *pelmMediaRegistry = pelmGlobal->createChild("MediaRegistry"); 1235 1236 xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks"); 1237 for (MediaList::const_iterator it = llHardDisks.begin(); 1238 it != llHardDisks.end(); 1239 ++it) 1240 { 1241 writeHardDisk(*pelmHardDisks, *it, 0); 1242 } 1243 1244 xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages"); 1245 for (MediaList::const_iterator it = llDvdImages.begin(); 1246 it != llDvdImages.end(); 1247 ++it) 1248 { 1249 const Medium &mdm = *it; 1250 xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image"); 1251 pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly()); 1252 pelmMedium->setAttribute("location", mdm.strLocation); 1253 if (mdm.strDescription.length()) 1254 pelmMedium->setAttribute("Description", mdm.strDescription); 1255 } 1256 1257 xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages"); 1258 for (MediaList::const_iterator it = llFloppyImages.begin(); 1259 it != llFloppyImages.end(); 1260 ++it) 1261 { 1262 const Medium &mdm = *it; 1263 xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image"); 1264 pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly()); 1265 pelmMedium->setAttribute("location", mdm.strLocation); 1266 if (mdm.strDescription.length()) 1267 pelmMedium->setAttribute("Description", mdm.strDescription); 1268 } 1318 buildMediaRegistry(*pelmGlobal, mediaRegistry); 1269 1319 1270 1320 xml::ElementNode *pelmNetserviceRegistry = pelmGlobal->createChild("NetserviceRegistry"); … … 1297 1347 pelmSysProps->setAttribute("LogHistoryCount", systemProperties.ulLogHistoryCount); 1298 1348 1299 writeUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),1349 buildUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"), 1300 1350 host.llUSBDeviceFilters, 1301 1351 true); // fHostMode … … 1745 1795 && (hardwareMachine == c.hardwareMachine) // this one's deep 1746 1796 && (storageMachine == c.storageMachine) // this one's deep 1797 && (mediaRegistry == c.mediaRegistry) // this one's deep 1747 1798 && (mapExtraDataItems == c.mapExtraDataItems) // this one's deep 1748 1799 && (llFirstSnapshot == c.llFirstSnapshot) // this one's deep … … 3363 3414 pelmUSB->setAttribute("enabledEhci", hw.usbController.fEnabledEHCI); 3364 3415 3365 writeUSBDeviceFilters(*pelmUSB,3416 buildUSBDeviceFilters(*pelmUSB, 3366 3417 hw.usbController.llDeviceFilters, 3367 3418 false); // fHostMode … … 3898 3949 * In fl, the following flag bits are recognized: 3899 3950 * 3951 * -- BuildMachineXML_MediaRegistry: If set, the machine's media registry will 3952 * be written, if present. This is not set when called from OVF because OVF 3953 * has its own variant of a media registry. This flag is ignored unless the 3954 * settings version is at least v1.11 (VirtualBox 3.3). 3955 * 3900 3956 * -- BuildMachineXML_IncludeSnapshots: If set, descend into the snapshots tree 3901 3957 * of the machine and write out <Snapshot> and possibly more snapshots under 3902 * that, if snapshots are present. Otherwise all snapshots are suppressed. 3958 * that, if snapshots are present. Otherwise all snapshots are suppressed 3959 * (when called from OVF). 3903 3960 * 3904 3961 * -- BuildMachineXML_WriteVboxVersionAttribute: If set, add a settingsVersion … … 3909 3966 * -- BuildMachineXML_SkipRemovableMedia: If set, removable media attachments 3910 3967 * (DVDs, floppies) are silently skipped. This is for the OVF export case 3911 * until we support copying ISO and RAW media as well. This fla sis ignored3968 * until we support copying ISO and RAW media as well. This flag is ignored 3912 3969 * unless the settings version is at least v1.9, which is always the case 3913 3970 * when this gets called for OVF export. … … 3960 4017 } 3961 4018 3962 writeExtraData(elmMachine, mapExtraDataItems);4019 buildExtraData(elmMachine, mapExtraDataItems); 3963 4020 3964 4021 if ( (fl & BuildMachineXML_IncludeSnapshots) … … 3971 4028 !!(fl & BuildMachineXML_SkipRemovableMedia), 3972 4029 pllElementsWithUuidAttributes); 4030 4031 if ( (fl & BuildMachineXML_MediaRegistry) 4032 && (m->sv >= SettingsVersion_v1_11) 4033 ) 4034 buildMediaRegistry(elmMachine, mediaRegistry); 3973 4035 } 3974 4036 … … 4195 4257 m->sv = SettingsVersion_v1_10; 4196 4258 4197 // VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main .4259 // VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main 4198 4260 if (m->sv < SettingsVersion_v1_10) 4199 4261 { 4200 4262 NetworkAdaptersList::const_iterator netit; 4201 4263 for (netit = hardwareMachine.llNetworkAdapters.begin(); 4202 netit != hardwareMachine.llNetworkAdapters.end(); ++netit) 4264 netit != hardwareMachine.llNetworkAdapters.end(); 4265 ++netit) 4203 4266 { 4204 4267 if (netit->ulBandwidthLimit) … … 4260 4323 if (hardwareMachine.ulCpuPriority != 100) 4261 4324 m->sv = SettingsVersion_v1_11; 4325 4326 // .. and we now have per-machine media registries 4327 if ( mediaRegistry.llHardDisks.size() 4328 || mediaRegistry.llDvdImages.size() 4329 || mediaRegistry.llFloppyImages.size() 4330 ) 4331 m->sv = SettingsVersion_v1_11; 4262 4332 } 4263 4333 } … … 4282 4352 xml::ElementNode *pelmMachine = m->pelmRoot->createChild("Machine"); 4283 4353 buildMachineXML(*pelmMachine, 4284 MachineConfigFile::BuildMachineXML_IncludeSnapshots, 4354 MachineConfigFile::BuildMachineXML_IncludeSnapshots 4355 | MachineConfigFile::BuildMachineXML_MediaRegistry, 4285 4356 // but not BuildMachineXML_WriteVboxVersionAttribute 4286 4357 NULL); /* pllElementsWithUuidAttributes */
Note:
See TracChangeset
for help on using the changeset viewer.