VirtualBox

Changeset 28689 in vbox


Ignore:
Timestamp:
Apr 24, 2010 6:23:57 PM (15 years ago)
Author:
vboxsync
Message:

XmlFileWrite::write: Added a fSafe argument for safe writing of the xml file. See method description for details.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/cpp/xml.h

    r28199 r28689  
    11/** @file
    2  * VirtualBox XML helper APIs.
     2 * IPRT - XML Helper APIs.
    33 */
    44
    55/*
    6  * Copyright (C) 2007-2009 Sun Microsystems, Inc.
     6 * Copyright (C) 2007-2010 Sun Microsystems, Inc.
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2828 */
    2929
    30 #ifndef ___VBox_vboxxml_h
    31 #define ___VBox_vboxxml_h
     30#ifndef ___iprt_xml_h
     31#define ___iprt_xml_h
    3232
    3333#ifndef IN_RING3
     
    288288     * @param aMode     File mode.
    289289     * @param aFileName File name.
    290      */
    291     File(Mode aMode, const char *aFileName);
     290     * @param aFlushIt  Whether to flush a writable file before closing it.
     291     */
     292    File(Mode aMode, const char *aFileName, bool aFlushIt = false);
    292293
    293294    /**
     
    308309     * @param aHandle   Open file handle.
    309310     * @param aFileName File name (for reference).
    310      */
    311     File(RTFILE aHandle, const char *aFileName = NULL);
     311     * @param aFlushIt  Whether to flush a writable file before closing it.
     312     */
     313    File(RTFILE aHandle, const char *aFileName = NULL, bool aFlushIt = false);
    312314
    313315    /**
     
    669671    ~XmlFileWriter();
    670672
    671     void write(const char *pcszFilename);
     673    /**
     674     * Writes the XML document to the specified file.
     675     *
     676     * @param   pcszFilename    The name of the output file.
     677     * @param   fSafe           If @c true, some extra safety precautions will be
     678     *                          taken when writing the file:
     679     *                              -# The file is written with a '-tmp' suffix.
     680     *                              -# It is flushed to disk after writing.
     681     *                              -# Any original file is renamed to '-prev'.
     682     *                              -# The '-tmp' file is then renamed to the
     683     *                                 specified name.
     684     *                              -# The directory changes are flushed to disk.
     685     */
     686    void write(const char *pcszFilename, bool fSafe);
    672687
    673688    static int WriteCallback(void *aCtxt, const char *aBuf, int aLen);
     
    675690
    676691private:
     692    void writeInternal(const char *pcszFilename, bool fSafe);
     693
    677694    /* Obscure class data */
    678695    struct Data;
     
    688705} // end namespace xml
    689706
    690 #endif /* ___VBox_vboxxml_h */
     707#endif /* !___iprt_xml_h */
  • trunk/src/VBox/Main/ApplianceImplExport.cpp

    r28596 r28689  
    15481548        // now go write the XML
    15491549        xml::XmlFileWriter writer(doc);
    1550         writer.write(locInfo.strPath.c_str());
     1550        writer.write(locInfo.strPath.c_str(), false /*fSafe*/);
    15511551
    15521552        /* Create & write the manifest file */
  • trunk/src/VBox/Main/xml/Settings.cpp

    r28434 r28689  
    12931293    // now go write the XML
    12941294    xml::XmlFileWriter writer(*m->pDoc);
    1295     writer.write(m->strFilename.c_str());
     1295    writer.write(m->strFilename.c_str(), true /*fSafe*/);
    12961296
    12971297    m->fFileExists = true;
     
    40514051        // now go write the XML
    40524052        xml::XmlFileWriter writer(*m->pDoc);
    4053         writer.write(m->strFilename.c_str());
     4053        writer.write(m->strFilename.c_str(), true /*fSafe*/);
    40544054
    40554055        m->fFileExists = true;
  • trunk/src/VBox/Runtime/r3/xml.cpp

    r28199 r28689  
     1/* $Id$ */
    12/** @file
    2  * VirtualBox XML Manipulation API.
     3 * IPRT - XML Manipulation API.
    34 */
    45
    56/*
    6  * Copyright (C) 2007-2009 Sun Microsystems, Inc.
     7 * Copyright (C) 2007-2010 Sun Microsystems, Inc.
    78 *
    89 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2829 */
    2930
    30 #include <iprt/cdefs.h>
     31#include <iprt/dir.h>
     32#include <iprt/file.h>
    3133#include <iprt/err.h>
    32 #include <iprt/file.h>
     34#include <iprt/param.h>
     35#include <iprt/path.h>
    3336#include <iprt/cpp/lock.h>
    3437#include <iprt/cpp/xml.h>
     
    179182    RTFILE handle;
    180183    bool opened : 1;
     184    bool flushOnClose : 1;
    181185};
    182186
    183 File::File(Mode aMode, const char *aFileName)
     187File::File(Mode aMode, const char *aFileName, bool aFlushIt /* = false */)
    184188    : m(new Data())
    185189{
    186190    m->strFileName = aFileName;
     191    m->flushOnClose = aFlushIt;
    187192
    188193    uint32_t flags = 0;
     
    208213
    209214    m->opened = true;
    210 }
    211 
    212 File::File(RTFILE aHandle, const char *aFileName /* = NULL */)
     215    m->flushOnClose = aFlushIt && (flags & RTFILE_O_ACCESS_MASK) != RTFILE_O_READ;
     216}
     217
     218File::File(RTFILE aHandle, const char *aFileName /* = NULL */, bool aFlushIt /* = false */)
    213219    : m(new Data())
    214220{
    215221    if (aHandle == NIL_RTFILE)
    216         throw EInvalidArg (RT_SRC_POS);
     222        throw EInvalidArg(RT_SRC_POS);
    217223
    218224    m->handle = aHandle;
     
    221227        m->strFileName = aFileName;
    222228
    223     setPos (0);
     229    m->flushOnClose = aFlushIt;
     230
     231    setPos(0);
    224232}
    225233
    226234File::~File()
    227235{
     236    if (m->flushOnClose)
     237    {
     238        RTFileFlush(m->handle);
     239        if (!m->strFileName.isEmpty())
     240            RTDirFlushParent(m->strFileName.c_str());
     241    }
     242
    228243    if (m->opened)
    229244        RTFileClose(m->handle);
     
    253268
    254269    /* check if we overflow int64_t and move to INT64_MAX first */
    255     if (((int64_t) aPos) < 0)
     270    if ((int64_t)aPos < 0)
    256271    {
    257272        vrc = RTFileSeek(m->handle, INT64_MAX, method, &p);
     
    13601375    iprt::MiniString error;
    13611376
    1362     IOContext(const char *pcszFilename, File::Mode mode)
    1363         : file(mode, pcszFilename)
     1377    IOContext(const char *pcszFilename, File::Mode mode, bool fFlush = false)
     1378        : file(mode, pcszFilename, fFlush)
    13641379    {
    13651380    }
     
    13861401struct WriteContext : IOContext
    13871402{
    1388     WriteContext(const char *pcszFilename)
    1389         : IOContext(pcszFilename, File::Mode_Overwrite)
     1403    WriteContext(const char *pcszFilename, bool fFlush)
     1404        : IOContext(pcszFilename, File::Mode_Overwrite, fFlush)
    13901405    {
    13911406    }
     
    14731488}
    14741489
    1475 void XmlFileWriter::write(const char *pcszFilename)
    1476 {
    1477     WriteContext context(pcszFilename);
     1490void XmlFileWriter::writeInternal(const char *pcszFilename, bool fSafe)
     1491{
     1492    WriteContext context(pcszFilename, fSafe);
    14781493
    14791494    GlobalLock lock;
     
    15071522}
    15081523
     1524void XmlFileWriter::write(const char *pcszFilename, bool fSafe)
     1525{
     1526    if (!fSafe)
     1527        writeInternal(pcszFilename, fSafe);
     1528    else
     1529    {
     1530        /* Empty string and directory spec must be avoid. */
     1531        if (RTPathFilename(pcszFilename) == NULL)
     1532            throw xml::LogicError(RT_SRC_POS);
     1533
     1534        /* Construct both filenames first to ease error handling.  */
     1535        char szTmpFilename[RTPATH_MAX];
     1536        int rc = RTStrCopy(szTmpFilename, sizeof(szTmpFilename) - sizeof("-tmp") + 1, pcszFilename);
     1537        if (RT_FAILURE(rc))
     1538            throw EIPRTFailure(rc, "RTStrCopy");
     1539        strcat(szTmpFilename, "-tmp");
     1540
     1541        char szPrevFilename[RTPATH_MAX];
     1542        rc = RTStrCopy(szPrevFilename, sizeof(szPrevFilename) - sizeof("-prev") + 1, pcszFilename);
     1543        if (RT_FAILURE(rc))
     1544            throw EIPRTFailure(rc, "RTStrCopy");
     1545        strcat(szPrevFilename, "-prev");
     1546
     1547        /* Write the XML document to the temporary file.  */
     1548        writeInternal(szTmpFilename, fSafe);
     1549
     1550        /* Make a backup of any existing file (ignore failure). */
     1551        uint64_t cbPrevFile;
     1552        rc = RTFileQuerySize(pcszFilename, &cbPrevFile);
     1553        if (RT_SUCCESS(rc) && cbPrevFile >= 16)
     1554            RTFileRename(pcszFilename, szPrevFilename, RTPATHRENAME_FLAGS_REPLACE);
     1555
     1556        /* Commit the temporary file. Just leave the tmp file behind on failure. */
     1557        rc = RTFileRename(szTmpFilename, pcszFilename, RTPATHRENAME_FLAGS_REPLACE);
     1558        if (RT_FAILURE(rc))
     1559            throw EIPRTFailure(rc, "Failed to replace '%s' with '%s'", pcszFilename, szTmpFilename);
     1560
     1561        /* Flush the directory changes (required on linux at least). */
     1562        RTPathStripFilename(szTmpFilename);
     1563        rc = RTDirFlush(szTmpFilename);
     1564        AssertMsg(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED || rc == VERR_NOT_IMPLEMENTED, ("%Rrc\n", rc));
     1565    }
     1566}
     1567
    15091568int XmlFileWriter::WriteCallback(void *aCtxt, const char *aBuf, int aLen)
    15101569{
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