Ticket #3255: t3255_prevent_replay_overwrites_v6.patch

File t3255_prevent_replay_overwrites_v6.patch, 8.4 KB (added by elexis, 8 years ago)
  • source/ps/Replay.cpp

     
    2828#include "ps/Loader.h"
    2929#include "ps/Mod.h"
    3030#include "ps/Profile.h"
    3131#include "ps/ProfileViewer.h"
    3232#include "ps/Pyrogenesis.h"
     33#include "ps/Util.h"
     34#include "ps/VisualReplay.h"
    3335#include "scriptinterface/ScriptInterface.h"
    3436#include "scriptinterface/ScriptStats.h"
    3537#include "simulation2/Simulation2.h"
    3638#include "simulation2/helpers/SimulationCommand.h"
    3739
     40#include <ctime>
    3841#include <sstream>
    3942#include <fstream>
    4043#include <iomanip>
    4144
    42 #if MSC_VERSION
    43 #include <process.h>
    44 #define getpid _getpid // use the non-deprecated function name
    45 #endif
    46 
    4745static std::string Hexify(const std::string& s)
    4846{
    4947    std::stringstream str;
    5048    str << std::hex;
    5149    for (size_t i = 0; i < s.size(); ++i)
    void CReplayLogger::StartGame(JS::Mutabl  
    7068
    7169    // Add engine version and currently loaded mods for sanity checks when replaying
    7270    m_ScriptInterface.SetProperty(attribs, "engine_version", CStr(engine_version));
    7371    m_ScriptInterface.SetProperty(attribs, "mods", g_modsLoaded);
    7472
    75     // Construct the directory name based on the PID, to be relatively unique.
    76     // Append "-1", "-2" etc if we run multiple matches in a single session,
    77     // to avoid accidentally overwriting earlier logs.
    78     static int run = -1;
    79     do
    80     {
    81         std::wstringstream name;
    82         name << getpid();
    83         if (++run)
    84             name << "-" << run;
    85 
    86         m_Directory = psLogDir() / L"sim_log" / name.str();
    87     } while (DirectoryExists(m_Directory));
    88 
     73    m_Directory = getDateIndexSubdirectory(VisualReplay::GetDirectoryName());
     74    debug_printf("Writing replay to %s\n", m_Directory.string8().c_str());
    8975    CreateDirectories(m_Directory, 0700);
    9076
    9177    m_Stream = new std::ofstream(OsString(m_Directory / L"commands.txt").c_str(), std::ofstream::out | std::ofstream::trunc);
    9278    *m_Stream << "start " << m_ScriptInterface.StringifyJSON(attribs, false) << "\n";
    9379}
  • source/ps/Util.cpp

     
    1 /* Copyright (C) 2014 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    Status tex_write(Tex* t, const VfsPath&  
    191191
    192192    (void)da_free(&da);
    193193    return ret;
    194194}
    195195
     196/**
     197 * Return an unused directory, based on date and index (for example 2016-02-09_0001)
     198 */
     199OsPath getDateIndexSubdirectory(const OsPath& parentDir)
     200{
     201    const std::time_t timestamp = std::time(nullptr);
     202    const struct std::tm* now = std::localtime(&timestamp);
     203
     204    int i = 0;
     205    OsPath path;
     206    char directory[256];
     207
     208    do
     209    {
     210        sprintf(directory, "%04d-%02d-%02d_%04d", now->tm_year+1900, now->tm_mon+1, now->tm_mday, ++i);
     211        path = parentDir / CStr(directory);
     212    } while (DirectoryExists(path) || FileExists(path));
     213
     214    return path;
     215}
    196216
    197217static size_t s_nextScreenshotNumber;
    198218
    199219// <extension> identifies the file format that is to be written
    200220// (case-insensitive). examples: "bmp", "png", "jpg".
  • source/ps/Util.h

     
    1 /* Copyright (C) 2009 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
    struct Tex;  
    2424
    2525extern void WriteSystemInfo();
    2626
    2727extern const wchar_t* ErrorString(int err);
    2828
     29extern OsPath getDateIndexSubdirectory(const OsPath& parentDir);
     30
    2931extern void WriteScreenshot(const VfsPath& extension);
    3032extern void WriteBigScreenshot(const VfsPath& extension, int tiles);
    3133
    3234extern Status tex_write(Tex* t, const VfsPath& filename);
    3335
  • source/ps/VisualReplay.cpp

     
    1 /* Copyright (C) 2015 Wildfire Games.
     1/* Copyright (C) 2016 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
    55 * it under the terms of the GNU General Public License as published by
    66 * the Free Software Foundation, either version 2 of the License, or
     
    2525#include "network/NetClient.h"
    2626#include "network/NetServer.h"
    2727#include "ps/CLogger.h"
    2828#include "ps/Filesystem.h"
    2929#include "ps/Game.h"
     30#include "ps/GameSetup/Paths.h"
     31#include "ps/Mod.h"
    3032#include "ps/Pyrogenesis.h"
    3133#include "ps/Replay.h"
     34#include "ps/Util.h"
    3235#include "scriptinterface/ScriptInterface.h"
    3336
    3437/**
    3538 * Filter too short replays (value in seconds).
    3639 */
    3740const u8 minimumReplayDuration = 3;
    3841
    3942OsPath VisualReplay::GetDirectoryName()
    4043{
    41     return OsPath(psLogDir() / L"sim_log");
     44    const Paths paths(g_args);
     45    return OsPath(paths.UserData() / "replays" / engine_version);
    4246}
    4347
    4448void VisualReplay::StartVisualReplay(const CStrW& directory)
    4549{
    4650    ENSURE(!g_NetServer);
  • source/simulation2/Simulation2.cpp

     
    3939#include "ps/ConfigDB.h"
    4040#include "ps/Filesystem.h"
    4141#include "ps/Loader.h"
    4242#include "ps/Profile.h"
    4343#include "ps/Pyrogenesis.h"
     44#include "ps/Util.h"
    4445#include "ps/XML/Xeromyces.h"
    4546
    4647#include <iomanip>
    4748
    48 #if MSC_VERSION
    49 #include <process.h>
    50 #define getpid _getpid // use the non-deprecated function name
    51 #endif
    52 
    5349static std::string Hexify(const std::string& s) // TODO: shouldn't duplicate this function in so many places
    5450{
    5551    std::stringstream str;
    5652    str << std::hex;
    5753    for (size_t i = 0; i < s.size(); ++i)
    public:  
    7773        if (CConfigDB::IsInitialised())
    7874        {
    7975            CFG_GET_VAL("ooslog", m_EnableOOSLog);
    8076            CFG_GET_VAL("serializationtest", m_EnableSerializationTest);
    8177        }
     78
     79        m_OOSLogPath = getDateIndexSubdirectory(psLogDir() / "oos_logs");
     80
     81        if (m_EnableOOSLog)
     82            debug_printf("Writing ooslogs to %s\n", m_OOSLogPath.string8().c_str());
    8283    }
    8384
    8485    ~CSimulation2Impl()
    8586    {
    8687        UnregisterFileReloadFunc(ReloadChangedFileCB, this);
    public:  
    130131    std::set<VfsPath> m_LoadedScripts;
    131132
    132133    uint32_t m_TurnNumber;
    133134
    134135    bool m_EnableOOSLog;
    135 
     136    OsPath m_OOSLogPath;
    136137
    137138    // Functions and data for the serialization test mode: (see Update() for relevant comments)
    138139
    139140    bool m_EnableSerializationTest;
    140141
    void CSimulation2Impl::DumpSerialization  
    293294
    294295void CSimulation2Impl::ReportSerializationFailure(
    295296    SerializationTestState* primaryStateBefore, SerializationTestState* primaryStateAfter,
    296297    SerializationTestState* secondaryStateBefore, SerializationTestState* secondaryStateAfter)
    297298{
    298     OsPath path = psLogDir() / "oos_log";
     299    const OsPath path = getDateIndexSubdirectory(psLogDir() / "serializationtest");
     300    debug_printf("Writing serializationtest-data to %s\n", path.string8().c_str());
    299301    CreateDirectories(path, 0700);
    300302
    301303    // Clean up obsolete files from previous runs
    302304    wunlink(path / "hash.before.a");
    303305    wunlink(path / "hash.before.b");
    void CSimulation2Impl::Interpolate(float  
    547549
    548550void CSimulation2Impl::DumpState()
    549551{
    550552    PROFILE("DumpState");
    551553
    552     std::stringstream pid;
    553     pid << getpid();
    554554    std::stringstream name;\
    555555    name << std::setw(5) << std::setfill('0') << m_TurnNumber << ".txt";
    556     OsPath path = psLogDir() / "sim_log" / pid.str() / name.str();
     556    const OsPath path = m_OOSLogPath / name.str();
    557557    CreateDirectories(path.Parent(), 0700);
    558558    std::ofstream file (OsString(path).c_str(), std::ofstream::out | std::ofstream::trunc);
    559559
    560560    file << "State hash: " << std::hex;
    561561    std::string hashRaw;
    CSimulation2::~CSimulation2()  
    587587// Forward all method calls to the appropriate CSimulation2Impl/CComponentManager methods:
    588588
    589589void CSimulation2::EnableOOSLog()
    590590{
    591591    m->m_EnableOOSLog = true;
     592    debug_printf("Writing ooslogs to %s\n", m->m_OOSLogPath.string8().c_str());
    592593}
    593594
    594595void CSimulation2::EnableSerializationTest()
    595596{
    596597    m->m_EnableSerializationTest = true;