VirtualBox

Changeset 31464 in vbox


Ignore:
Timestamp:
Aug 9, 2010 9:15:40 AM (15 years ago)
Author:
vboxsync
Message:

Main: support per-machine media registries in XML settings (not yet used)

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/settings.h

    r31303 r31464  
    6060
    6161class ConfigFileError;
    62 
    63 ////////////////////////////////////////////////////////////////////////////////
    64 //
    65 // Helper classes
    66 //
    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 MachineConfigFile
    76  * which contains some common logic for both.
    77  */
    78 class ConfigFileBase
    79 {
    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 &timestamp,
    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 };
    12062
    12163////////////////////////////////////////////////////////////////////////////////
     
    15799};
    158100
     101typedef std::map<com::Utf8Str, com::Utf8Str> PropertiesMap;
     102
     103// ExtraDataItem (used by both VirtualBox.xml and machines XML)
     104typedef std::map<com::Utf8Str, com::Utf8Str> ExtraDataItemsMap;
     105struct USBDeviceFilter;
     106typedef std::list<USBDeviceFilter> USBDeviceFiltersList;
     107
     108struct Medium;
     109typedef 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 */
     116struct 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 */
     138struct 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 */
     151class ConfigFileBase
     152{
     153public:
     154    bool fileExists();
     155
     156    void copyBaseFrom(const ConfigFileBase &b);
     157
     158protected:
     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 &timestamp,
     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
     194private:
     195    // prohibit copying (Data contains pointers to XML which cannot be copied)
     196    ConfigFileBase(const ConfigFileBase&);
     197
     198    friend class ConfigFileError;
     199};
     200
    159201////////////////////////////////////////////////////////////////////////////////
    160202//
     
    182224};
    183225
    184 typedef std::map<com::Utf8Str, com::Utf8Str> PropertiesMap;
    185 
    186 struct Medium;
    187 typedef std::list<Medium> MediaList;
    188 
    189 struct Medium
    190 {
    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 false
    198     PropertiesMap   properties;
    199     MediumType_T    hdType;
    200 
    201     MediaList       llChildren;         // only used with hard disks
    202 };
    203 
    204226struct MachineRegistryEntry
    205227{
     
    225247    MainConfigFile(const com::Utf8Str *pstrFilename);
    226248
    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);
    230249    void readMachineRegistry(const xml::ElementNode &elmMachineRegistry);
    231250    void readDHCPServers(const xml::ElementNode &elmDHCPServers);
    232251
    233     void writeHardDisk(xml::ElementNode &elmMedium,
    234                        const Medium &m,
    235                        uint32_t level);
    236252    void write(const com::Utf8Str strFilename);
    237253
    238254    Host                    host;
    239255    SystemProperties        systemProperties;
    240     MediaList               llHardDisks,
    241                             llDvdImages,
    242                             llFloppyImages;
     256    MediaRegistry           mediaRegistry;
    243257    MachinesRegistry        llMachines;
    244258    DHCPServersList         llDhcpServers;
     
    865879    Hardware                hardwareMachine;
    866880    Storage                 storageMachine;
     881    MediaRegistry           mediaRegistry;
    867882
    868883    ExtraDataItemsMap       mapExtraDataItems;
     
    882897        BuildMachineXML_IncludeSnapshots = 0x01,
    883898        BuildMachineXML_WriteVboxVersionAttribute = 0x02,
    884         BuildMachineXML_SkipRemovableMedia = 0x02
     899        BuildMachineXML_SkipRemovableMedia = 0x04,
     900        BuildMachineXML_MediaRegistry = 0x08
    885901    };
    886902    void buildMachineXML(xml::ElementNode &elmMachine,
  • trunk/src/VBox/Main/ApplianceImplExport.cpp

    r30764 r31464  
    13011301                                   settings::MachineConfigFile::BuildMachineXML_WriteVboxVersionAttribute
    13021302                                 | settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia,
    1303                                         // but not BuildMachineXML_IncludeSnapshots
     1303                                        // but not BuildMachineXML_IncludeSnapshots nor BuildMachineXML_MediaRegistry
    13041304                                 pllElementsWithUuidAttributes);
    13051305        delete pConfig;
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r31388 r31464  
    599599    HRESULT rc = S_OK;
    600600    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();
    603603         ++it)
    604604    {
     
    617617    }
    618618
    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();
    621621         ++it)
    622622    {
     
    632632    }
    633633
    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();
    636636         ++it)
    637637    {
     
    32903290        /* now copy the temp data to the config file under the VirtualBox lock */
    32913291        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;
    32953295        m->pMainConfigFile->llDhcpServers = dhcpServersTemp;
    32963296
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r31334 r31464  
    468468    <const name="v1_11"     value="13">
    469469      <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
    471471           -->
    472472    </const>
  • trunk/src/VBox/Main/xml/Settings.cpp

    r31301 r31464  
    208208////////////////////////////////////////////////////////////////////////////////
    209209//
     210// MediaRegistry
     211//
     212////////////////////////////////////////////////////////////////////////////////
     213
     214bool 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
     226bool MediaRegistry::operator==(const MediaRegistry &m) const
     227{
     228    return    llHardDisks == m.llHardDisks
     229           && llDvdImages == m.llDvdImages
     230           && llFloppyImages == m.llFloppyImages;
     231}
     232
     233////////////////////////////////////////////////////////////////////////////////
     234//
    210235// ConfigFileBase
    211236//
     
    526551
    527552/**
    528  * Adds a "version" attribute to the given XML element with the
    529  * VirtualBox settings version (e.g. "1.10-linux"). Used by
    530  * the XML format for the root element and by the OVF export
    531  * for the vbox:Machine element.
    532  * @param elm
    533  */
    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 write
    564             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 the
    576  * root "VirtualBox" element set up. This is used by both
    577  * MainConfigFile and MachineConfigFile at the beginning of writing
    578  * out their XML.
    579  *
    580  * Before calling this, it is the responsibility of the caller to
    581  * set the "sv" member to the required settings version that is to
    582  * be written. For newly created files, the settings version will be
    583  * the latest (1.11); for files read in from disk earlier, it will be
    584  * the settings version indicated in the file. However, this method
    585  * will silently make sure that the settings version is always
    586  * at least 1.7 and change it if necessary, since there is no write
    587  * 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 element
    598     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 version
    602     // and need to make a backup, so the user can go back to an earlier
    603     // 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_REPLACE
    618 
    619         // do this only once
    620         m->svRead = SettingsVersion_Null;
    621     }
    622 }
    623 
    624 /**
    625  * Creates an <ExtraData> node under the given parent element with
    626  * <ExtraDataItem> childern according to the contents of the given
    627  * map.
    628  * This is in ConfigFileBase because it's used in both MainConfigFile
    629  * MachineConfigFile, which both can have extradata.
    630  *
    631  * @param elmParent
    632  * @param me
    633  */
    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 to
    655  * the contents of the given USBDeviceFiltersList. This is in ConfigFileBase
    656  * because it's used in both MainConfigFile (for host filters) and
    657  * MachineConfigFile (for machine filters).
    658  *
    659  * If fHostMode is true, this means that we're supposed to write filters
    660  * for the IHost interface (respect "action", omit "strRemote" and
    661  * "ulMaskedInterfaces" in struct USBDeviceFilter).
    662  *
    663  * @param elmParent
    664  * @param ll
    665  * @param fHostMode
    666  */
    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         else
    702         {
    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 by
    713  * 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 written
    723  * to disk, or both.
    724  * @return
    725  */
    726 bool ConfigFileBase::fileExists()
    727 {
    728     return m->fFileExists;
    729 }
    730 
    731 /**
    732  * Copies the base variables from another instance. Used by Machine::saveSettings
    733  * so that the settings version does not get lost when a copy of the Machine settings
    734  * file is made to see if settings have actually changed.
    735  * @param b
    736  */
    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.xml
    745 //
    746 ////////////////////////////////////////////////////////////////////////////////
    747 
    748 /**
    749  * Comparison operator. This gets called from MachineConfigFile::operator==,
    750  * which in turn gets called from Machine::saveSettings to figure out whether
    751  * machine settings have really changed and thus need to be written out to disk.
    752  */
    753 bool USBDeviceFilter::operator==(const USBDeviceFilter &u) const
    754 {
    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 // MainConfigFile
    775 //
    776 ////////////////////////////////////////////////////////////////////////////////
    777 
    778 /**
    779  * Reads one <MachineEntry> from the main VirtualBox.xml file.
    780  * @param elmMachineRegistry
    781  */
    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             else
    801                 throw ConfigFileError(this, pelmChild1, N_("Required MachineEntry/@uuid or @src attribute is missing"));
    802         }
    803     }
    804 }
    805 
    806 /**
    807553 * Reads a media registry entry from the main VirtualBox.xml file.
    808554 *
     
    816562 * @param llMedia
    817563 */
    818 void MainConfigFile::readMedium(MediaType t,
     564void ConfigFileBase::readMedium(MediaType t,
    819565                                const xml::ElementNode &elmMedium,  // HardDisk node if root; if recursing,
    820566                                                                    // child HardDisk node or DiffHardDisk node for pre-1.4
     
    986732
    987733/**
    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 *
    990742 * @param elmMediaRegistry
    991743 */
    992 void MainConfigFile::readMediaRegistry(const xml::ElementNode &elmMediaRegistry)
     744void ConfigFileBase::readMediaRegistry(const xml::ElementNode &elmMediaRegistry,
     745                                       MediaRegistry &mr)
    993746{
    994747    xml::NodesLoop nl1(elmMediaRegistry);
     
    1015768                readMedium(t,
    1016769                           *pelmMedium,
    1017                            llHardDisks);      // list to append hard disk data to: the root list
     770                           mr.llHardDisks);      // list to append hard disk data to: the root list
    1018771            else if (    t == DVDImage
    1019772                      && (pelmMedium->nameEquals("Image"))
     
    1021774                readMedium(t,
    1022775                           *pelmMedium,
    1023                            llDvdImages);      // list to append dvd images to: the root list
     776                           mr.llDvdImages);      // list to append dvd images to: the root list
    1024777            else if (    t == FloppyImage
    1025778                      && (pelmMedium->nameEquals("Image"))
     
    1027780                readMedium(t,
    1028781                           *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 */
     794void 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 */
     849void 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 */
     895void 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 */
     928void 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 */
     981void 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 */
     1036void 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 */
     1080void 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 */
     1091bool 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 */
     1102void 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 */
     1118bool 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 */
     1147void 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"));
    10301167        }
    10311168    }
     
    11091246                                 )
    11101247                            )
    1111                         readMediaRegistry(*pelmGlobalChild);
     1248                        readMediaRegistry(*pelmGlobalChild, mediaRegistry);
    11121249                    else if (pelmGlobalChild->nameEquals("NetserviceRegistry"))
    11131250                    {
     
    11551292
    11561293/**
    1157  * Creates a single <HardDisk> element for the given Medium structure
    1158  * and recurses to write the child hard disks underneath. Called from
    1159  * MainConfigFile::write().
    1160  *
    1161  * @param elmMedium
    1162  * @param m
    1163  * @param level
    1164  */
    1165 void MainConfigFile::writeHardDisk(xml::ElementNode &elmMedium,
    1166                                    const Medium &mdm,
    1167                                    uint32_t level)          // 0 for "root" call, incremented with each recursion
    1168 {
    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 type
    1188     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 children
    1203         writeHardDisk(*pelmHardDisk, // parent
    1204                       *it,           // settings::Medium
    1205                       ++level);      // recursion level
    1206     }
    1207 }
    1208 
    1209 /**
    12101294 * Called from the IVirtualBox interface to write out VirtualBox.xml. This
    12111295 * builds an XML DOM tree and writes it out to disk.
     
    12181302    xml::ElementNode *pelmGlobal = m->pelmRoot->createChild("Global");
    12191303
    1220     writeExtraData(*pelmGlobal, mapExtraDataItems);
     1304    buildExtraData(*pelmGlobal, mapExtraDataItems);
    12211305
    12221306    xml::ElementNode *pelmMachineRegistry = pelmGlobal->createChild("MachineRegistry");
     
    12321316    }
    12331317
    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);
    12691319
    12701320    xml::ElementNode *pelmNetserviceRegistry = pelmGlobal->createChild("NetserviceRegistry");
     
    12971347    pelmSysProps->setAttribute("LogHistoryCount", systemProperties.ulLogHistoryCount);
    12981348
    1299     writeUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),
     1349    buildUSBDeviceFilters(*pelmGlobal->createChild("USBDeviceFilters"),
    13001350                          host.llUSBDeviceFilters,
    13011351                          true);               // fHostMode
     
    17451795                 && (hardwareMachine            == c.hardwareMachine)       // this one's deep
    17461796                 && (storageMachine             == c.storageMachine)        // this one's deep
     1797                 && (mediaRegistry              == c.mediaRegistry)         // this one's deep
    17471798                 && (mapExtraDataItems          == c.mapExtraDataItems)     // this one's deep
    17481799                 && (llFirstSnapshot            == c.llFirstSnapshot)       // this one's deep
     
    33633414    pelmUSB->setAttribute("enabledEhci", hw.usbController.fEnabledEHCI);
    33643415
    3365     writeUSBDeviceFilters(*pelmUSB,
     3416    buildUSBDeviceFilters(*pelmUSB,
    33663417                          hw.usbController.llDeviceFilters,
    33673418                          false);               // fHostMode
     
    38983949 * In fl, the following flag bits are recognized:
    38993950 *
     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 *
    39003956 *  --  BuildMachineXML_IncludeSnapshots: If set, descend into the snapshots tree
    39013957 *      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).
    39033960 *
    39043961 *  --  BuildMachineXML_WriteVboxVersionAttribute: If set, add a settingsVersion
     
    39093966 *  --  BuildMachineXML_SkipRemovableMedia: If set, removable media attachments
    39103967 *      (DVDs, floppies) are silently skipped. This is for the OVF export case
    3911  *      until we support copying ISO and RAW media as well.  This flas is ignored
     3968 *      until we support copying ISO and RAW media as well.  This flag is ignored
    39123969 *      unless the settings version is at least v1.9, which is always the case
    39133970 *      when this gets called for OVF export.
     
    39604017    }
    39614018
    3962     writeExtraData(elmMachine, mapExtraDataItems);
     4019    buildExtraData(elmMachine, mapExtraDataItems);
    39634020
    39644021    if (    (fl & BuildMachineXML_IncludeSnapshots)
     
    39714028                               !!(fl & BuildMachineXML_SkipRemovableMedia),
    39724029                               pllElementsWithUuidAttributes);
     4030
     4031    if (    (fl & BuildMachineXML_MediaRegistry)
     4032         && (m->sv >= SettingsVersion_v1_11)
     4033       )
     4034        buildMediaRegistry(elmMachine, mediaRegistry);
    39734035}
    39744036
     
    41954257        m->sv = SettingsVersion_v1_10;
    41964258
    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
    41984260    if (m->sv < SettingsVersion_v1_10)
    41994261    {
    42004262        NetworkAdaptersList::const_iterator netit;
    42014263        for (netit = hardwareMachine.llNetworkAdapters.begin();
    4202              netit != hardwareMachine.llNetworkAdapters.end(); ++netit)
     4264             netit != hardwareMachine.llNetworkAdapters.end();
     4265             ++netit)
    42034266        {
    42044267            if (netit->ulBandwidthLimit)
     
    42604323        if (hardwareMachine.ulCpuPriority != 100)
    42614324            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;
    42624332    }
    42634333}
     
    42824352        xml::ElementNode *pelmMachine = m->pelmRoot->createChild("Machine");
    42834353        buildMachineXML(*pelmMachine,
    4284                         MachineConfigFile::BuildMachineXML_IncludeSnapshots,
     4354                          MachineConfigFile::BuildMachineXML_IncludeSnapshots
     4355                        | MachineConfigFile::BuildMachineXML_MediaRegistry,
    42854356                            // but not BuildMachineXML_WriteVboxVersionAttribute
    42864357                        NULL); /* pllElementsWithUuidAttributes */
Note: See TracChangeset for help on using the changeset viewer.

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