Ticket #3255: t3255_prevent_replay_overwrites_v5.patch

File t3255_prevent_replay_overwrites_v5.patch, 6.5 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/VisualReplay.h"
    3334#include "scriptinterface/ScriptInterface.h"
    3435#include "scriptinterface/ScriptStats.h"
    3536#include "simulation2/Simulation2.h"
    3637#include "simulation2/helpers/SimulationCommand.h"
    3738
     39#include <ctime>
    3840#include <sstream>
    3941#include <fstream>
    4042#include <iomanip>
    4143
    42 #if MSC_VERSION
    43 #include <process.h>
    44 #define getpid _getpid // use the non-deprecated function name
    45 #endif
    46 
    4744static std::string Hexify(const std::string& s)
    4845{
    4946    std::stringstream str;
    5047    str << std::hex;
    5148    for (size_t i = 0; i < s.size(); ++i)
    CReplayLogger::~CReplayLogger()  
    6360    delete m_Stream;
    6461}
    6562
    6663void CReplayLogger::StartGame(JS::MutableHandleValue attribs)
    6764{
     65    const time_t timestamp = std::time(nullptr);
     66
    6867    // Add timestamp, since the file-modification-date can change
    69     m_ScriptInterface.SetProperty(attribs, "timestamp", std::to_string(std::time(nullptr)));
     68    m_ScriptInterface.SetProperty(attribs, "timestamp", std::to_string(timestamp));
    7069
    7170    // Add engine version and currently loaded mods for sanity checks when replaying
    7271    m_ScriptInterface.SetProperty(attribs, "engine_version", CStr(engine_version));
    7372    m_ScriptInterface.SetProperty(attribs, "mods", g_modsLoaded);
    7473
    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;
     74    // Construct directory name (for example 2015-11-02_0012)
     75    const struct tm* now = localtime(&timestamp);
     76    char directory[256];
     77    int i = 0;
    7978    do
    8079    {
    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));
     80        const CStr directoryFormat = ++i < 10000 ? "%04d-%02d-%02d_%04d" : "%04d-%02d-%02d_%d";
     81        sprintf(directory, directoryFormat.c_str(), now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, i);
     82        m_Directory = VisualReplay::GetDirectoryName() / CStr(directory);
     83    } while (DirectoryExists(m_Directory) || FileExists(m_Directory));
    8884
     85    debug_printf("Writing replay to %s\n", m_Directory.string8().c_str());
    8986    CreateDirectories(m_Directory, 0700);
    9087
    9188    m_Stream = new std::ofstream(OsString(m_Directory / L"commands.txt").c_str(), std::ofstream::out | std::ofstream::trunc);
    9289    *m_Stream << "start " << m_ScriptInterface.StringifyJSON(attribs, false) << "\n";
    9390}
  • 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"
    3234#include "scriptinterface/ScriptInterface.h"
    3335
    3436/**
     
    3638 */
    3739const u8 minimumReplayDuration = 3;
    3840
    3941OsPath VisualReplay::GetDirectoryName()
    4042{
    41     return OsPath(psLogDir() / L"sim_log");
     43    const Paths paths(g_args);
     44    return OsPath(paths.UserData() / "replays" / engine_version);
    4245}
    4346
    4447void VisualReplay::StartVisualReplay(const CStrW& directory)
    4548{
    4649    ENSURE(!g_NetServer);
  • source/simulation2/Simulation2.cpp

    public:  
    7777        if (CConfigDB::IsInitialised())
    7878        {
    7979            CFG_GET_VAL("ooslog", m_EnableOOSLog);
    8080            CFG_GET_VAL("serializationtest", m_EnableSerializationTest);
    8181        }
     82
     83        std::stringstream pid;
     84        pid << getpid();
     85        m_OOSLogPath = psLogDir() / "oos_logs" / pid.str();
     86
     87        if (m_EnableOOSLog)
     88            debug_printf("Writing ooslogs to %s\n", m_OOSLogPath.string8().c_str());
    8289    }
    8390
    8491    ~CSimulation2Impl()
    8592    {
    8693        UnregisterFileReloadFunc(ReloadChangedFileCB, this);
    public:  
    130137    std::set<VfsPath> m_LoadedScripts;
    131138
    132139    uint32_t m_TurnNumber;
    133140
    134141    bool m_EnableOOSLog;
    135 
     142    OsPath m_OOSLogPath;
    136143
    137144    // Functions and data for the serialization test mode: (see Update() for relevant comments)
    138 
    139145    bool m_EnableSerializationTest;
    140146
    141147    struct SerializationTestState
    142148    {
    143149        std::stringstream state;
    void CSimulation2Impl::DumpSerialization  
    293299
    294300void CSimulation2Impl::ReportSerializationFailure(
    295301    SerializationTestState* primaryStateBefore, SerializationTestState* primaryStateAfter,
    296302    SerializationTestState* secondaryStateBefore, SerializationTestState* secondaryStateAfter)
    297303{
    298     OsPath path = psLogDir() / "oos_log";
     304    OsPath path = psLogDir() / "serializationtest";
    299305    CreateDirectories(path, 0700);
    300306
     307    debug_printf("Writing serializationtest-data to %s\n", path.string8().c_str());
     308
    301309    // Clean up obsolete files from previous runs
    302310    wunlink(path / "hash.before.a");
    303311    wunlink(path / "hash.before.b");
    304312    wunlink(path / "debug.before.a");
    305313    wunlink(path / "debug.before.b");
    void CSimulation2Impl::Interpolate(float  
    547555
    548556void CSimulation2Impl::DumpState()
    549557{
    550558    PROFILE("DumpState");
    551559
    552     std::stringstream pid;
    553     pid << getpid();
    554560    std::stringstream name;\
    555561    name << std::setw(5) << std::setfill('0') << m_TurnNumber << ".txt";
    556     OsPath path = psLogDir() / "sim_log" / pid.str() / name.str();
     562    OsPath path = m_OOSLogPath / name.str();
    557563    CreateDirectories(path.Parent(), 0700);
    558564    std::ofstream file (OsString(path).c_str(), std::ofstream::out | std::ofstream::trunc);
    559565
    560566    file << "State hash: " << std::hex;
    561567    std::string hashRaw;
    CSimulation2::~CSimulation2()  
    583589{
    584590    delete m;
    585591}
    586592
    587593// Forward all method calls to the appropriate CSimulation2Impl/CComponentManager methods:
    588 
    589594void CSimulation2::EnableOOSLog()
    590595{
    591596    m->m_EnableOOSLog = true;
     597    debug_printf("Writing ooslogs to %s\n", m->m_OOSLogPath.string8().c_str());
    592598}
    593599
    594600void CSimulation2::EnableSerializationTest()
    595601{
    596602    m->m_EnableSerializationTest = true;