summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ban.cpp17
-rw-r--r--src/environment.cpp35
-rw-r--r--src/filesys.cpp25
-rw-r--r--src/filesys.h2
-rw-r--r--src/map.cpp28
-rw-r--r--src/mapgen.cpp17
-rw-r--r--src/serverlist.cpp20
-rw-r--r--src/settings.h21
-rw-r--r--src/subgame.cpp5
9 files changed, 101 insertions, 69 deletions
diff --git a/src/ban.cpp b/src/ban.cpp
index 75bae746f..f9d32b605 100644
--- a/src/ban.cpp
+++ b/src/ban.cpp
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <set>
#include "strfnd.h"
#include "log.h"
+#include "filesys.h"
BanManager::BanManager(const std::string &banfilepath):
m_banfilepath(banfilepath),
@@ -76,20 +77,20 @@ void BanManager::save()
{
JMutexAutoLock lock(m_mutex);
infostream<<"BanManager: saving to "<<m_banfilepath<<std::endl;
- std::ofstream os(m_banfilepath.c_str(), std::ios::binary);
-
- if(os.good() == false)
- {
- infostream<<"BanManager: failed saving to "<<m_banfilepath<<std::endl;
- throw SerializationError("BanManager::load(): Couldn't open file");
- }
+ std::ostringstream ss(std::ios_base::binary);
for(std::map<std::string, std::string>::iterator
i = m_ips.begin();
i != m_ips.end(); i++)
{
- os<<i->first<<"|"<<i->second<<"\n";
+ ss << i->first << "|" << i->second << "\n";
}
+
+ if(!fs::safeWriteToFile(m_banfilepath, ss.str())) {
+ infostream<<"BanManager: failed saving to "<<m_banfilepath<<std::endl;
+ throw SerializationError("BanManager::load(): Couldn't write file");
+ }
+
m_modified = false;
}
diff --git a/src/environment.cpp b/src/environment.cpp
index 35983aaaf..eacc2a008 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -437,13 +437,13 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
if(player->checkModified())
{
// Open file and serialize
- std::ofstream os(path.c_str(), std::ios_base::binary);
- if(os.good() == false)
+ std::ostringstream ss(std::ios_base::binary);
+ player->serialize(ss);
+ if(!fs::safeWriteToFile(path, ss.str()))
{
- infostream<<"Failed to overwrite "<<path<<std::endl;
+ infostream<<"Failed to write "<<path<<std::endl;
continue;
}
- player->serialize(os);
saved_players.insert(player);
} else {
saved_players.insert(player);
@@ -493,13 +493,13 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
/*infostream<<"Saving player "<<player->getName()<<" to "
<<path<<std::endl;*/
// Open file and serialize
- std::ofstream os(path.c_str(), std::ios_base::binary);
- if(os.good() == false)
+ std::ostringstream ss(std::ios_base::binary);
+ player->serialize(ss);
+ if(!fs::safeWriteToFile(path, ss.str()))
{
- infostream<<"Failed to overwrite "<<path<<std::endl;
+ infostream<<"Failed to write "<<path<<std::endl;
continue;
}
- player->serialize(os);
saved_players.insert(player);
}
}
@@ -581,19 +581,20 @@ void ServerEnvironment::saveMeta(const std::string &savedir)
std::string path = savedir + "/env_meta.txt";
// Open file and serialize
- std::ofstream os(path.c_str(), std::ios_base::binary);
- if(os.good() == false)
- {
- infostream<<"ServerEnvironment::saveMeta(): Failed to open "
- <<path<<std::endl;
- throw SerializationError("Couldn't save env meta");
- }
+ std::ostringstream ss(std::ios_base::binary);
Settings args;
args.setU64("game_time", m_game_time);
args.setU64("time_of_day", getTimeOfDay());
- args.writeLines(os);
- os<<"EnvArgsEnd\n";
+ args.writeLines(ss);
+ ss<<"EnvArgsEnd\n";
+
+ if(!fs::safeWriteToFile(path, ss.str()))
+ {
+ infostream<<"ServerEnvironment::saveMeta(): Failed to write "
+ <<path<<std::endl;
+ throw SerializationError("Couldn't save env meta");
+ }
}
void ServerEnvironment::loadMeta(const std::string &savedir)
diff --git a/src/filesys.cpp b/src/filesys.cpp
index 356d3018d..a1795c8ea 100644
--- a/src/filesys.cpp
+++ b/src/filesys.cpp
@@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <sstream>
+#include <fstream>
#include "log.h"
namespace fs
@@ -684,5 +686,28 @@ std::string RemoveRelativePathComponents(std::string path)
return path.substr(0, pos);
}
+bool safeWriteToFile(const std::string &path, const std::string &content)
+{
+ std::string tmp_file = path + ".~mt";
+
+ // Write to a tmp file
+ std::ofstream os(tmp_file.c_str(), std::ios::binary);
+ if (!os.good())
+ return false;
+ os << content;
+ os.flush();
+ os.close();
+ if (os.fail())
+ return false;
+
+ // Copy file
+#ifdef _WIN32
+ remove(path.c_str());
+ return (rename(tmp_file.c_str(), path.c_str()) == 0);
+#else
+ return (rename(tmp_file.c_str(), path.c_str()) == 0);
+#endif
+}
+
} // namespace fs
diff --git a/src/filesys.h b/src/filesys.h
index d0bf400c7..1b3659afe 100644
--- a/src/filesys.h
+++ b/src/filesys.h
@@ -98,6 +98,8 @@ std::string RemoveLastPathComponent(std::string path,
// this does not resolve symlinks and check for existence of directories.
std::string RemoveRelativePathComponents(std::string path);
+bool safeWriteToFile(const std::string &path, const std::string &content);
+
}//fs
#endif
diff --git a/src/map.cpp b/src/map.cpp
index da20b5b0e..331aa48d9 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -3490,20 +3490,21 @@ void ServerMap::saveMapMeta()
createDirs(m_savedir);
std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
- std::ofstream os(fullpath.c_str(), std::ios_base::binary);
- if(os.good() == false)
- {
- infostream<<"ERROR: ServerMap::saveMapMeta(): "
- <<"could not open"<<fullpath<<std::endl;
- throw FileNotGoodException("Cannot open chunk metadata");
- }
+ std::ostringstream ss(std::ios_base::binary);
Settings params;
m_emerge->setParamsToSettings(&params);
- params.writeLines(os);
+ params.writeLines(ss);
- os<<"[end_of_params]\n";
+ ss<<"[end_of_params]\n";
+
+ if(!fs::safeWriteToFile(fullpath, ss.str()))
+ {
+ infostream<<"ERROR: ServerMap::saveMapMeta(): "
+ <<"could not write "<<fullpath<<std::endl;
+ throw FileNotGoodException("Cannot save chunk metadata");
+ }
m_map_metadata_changed = false;
}
@@ -3574,11 +3575,12 @@ void ServerMap::saveSectorMeta(ServerMapSector *sector)
createDirs(dir);
std::string fullpath = dir + DIR_DELIM + "meta";
- std::ofstream o(fullpath.c_str(), std::ios_base::binary);
- if(o.good() == false)
- throw FileNotGoodException("Cannot open sector metafile");
+ std::ostringstream ss(std::ios_base::binary);
+
+ sector->serialize(ss, version);
- sector->serialize(o, version);
+ if(!fs::safeWriteToFile(fullpath, ss.str()))
+ throw FileNotGoodException("Cannot write sector metafile");
sector->differs_from_disk = false;
}
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 97d672b01..be65694aa 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen_v6.h"
#include "mapgen_v7.h"
#include "util/serialize.h"
+#include "filesys.h"
FlagDesc flagdesc_mapgen[] = {
{"trees", MG_TREES},
@@ -756,24 +757,26 @@ bool DecoSchematic::loadSchematicFile() {
2 - Fixed messy never/always place; 0 probability is now never, 0xFF is always
*/
void DecoSchematic::saveSchematicFile(INodeDefManager *ndef) {
- std::ofstream os(filename.c_str(), std::ios_base::binary);
+ std::ostringstream ss(std::ios_base::binary);
- writeU32(os, MTSCHEM_FILE_SIGNATURE); // signature
- writeU16(os, 2); // version
- writeV3S16(os, size); // schematic size
+ writeU32(ss, MTSCHEM_FILE_SIGNATURE); // signature
+ writeU16(ss, 2); // version
+ writeV3S16(ss, size); // schematic size
std::vector<content_t> usednodes;
int nodecount = size.X * size.Y * size.Z;
build_nnlist_and_update_ids(schematic, nodecount, &usednodes);
u16 numids = usednodes.size();
- writeU16(os, numids); // name count
+ writeU16(ss, numids); // name count
for (int i = 0; i != numids; i++)
- os << serializeString(ndef->get(usednodes[i]).name); // node names
+ ss << serializeString(ndef->get(usednodes[i]).name); // node names
// compressed bulk node data
- MapNode::serializeBulk(os, SER_FMT_VER_HIGHEST_WRITE, schematic,
+ MapNode::serializeBulk(ss, SER_FMT_VER_HIGHEST_WRITE, schematic,
nodecount, 2, 2, true);
+
+ fs::safeWriteToFile(filename, ss.str());
}
diff --git a/src/serverlist.cpp b/src/serverlist.cpp
index bc09f6c0a..4db5f3ecd 100644
--- a/src/serverlist.cpp
+++ b/src/serverlist.cpp
@@ -105,13 +105,11 @@ bool deleteEntry (ServerListSpec server)
}
std::string path = ServerList::getFilePath();
- std::ofstream stream (path.c_str());
- if (stream.is_open())
- {
- stream<<ServerList::serialize(serverlist);
- return true;
- }
- return false;
+ std::ostringstream ss(std::ios_base::binary);
+ ss << ServerList::serialize(serverlist);
+ if (!fs::safeWriteToFile(path, ss.str()))
+ return false;
+ return true;
}
/*
@@ -128,11 +126,9 @@ bool insert (ServerListSpec server)
serverlist.insert(serverlist.begin(), server);
std::string path = ServerList::getFilePath();
- std::ofstream stream (path.c_str());
- if (stream.is_open())
- {
- stream<<ServerList::serialize(serverlist);
- }
+ std::ostringstream ss(std::ios_base::binary);
+ ss << ServerList::serialize(serverlist);
+ fs::safeWriteToFile(path, ss.str());
return false;
}
diff --git a/src/settings.h b/src/settings.h
index e7b49b6d7..a9e0faa40 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <list>
#include <map>
#include <set>
+#include "filesys.h"
enum ValueType
{
@@ -308,14 +309,7 @@ public:
// Write stuff back
{
- std::ofstream os(filename);
- if(os.good() == false)
- {
- errorstream<<"Error opening configuration file"
- " for writing: \""
- <<filename<<"\""<<std::endl;
- return false;
- }
+ std::ostringstream ss(std::ios_base::binary);
/*
Write updated stuff
@@ -324,7 +318,7 @@ public:
i = objects.begin();
i != objects.end(); ++i)
{
- os<<(*i);
+ ss<<(*i);
}
/*
@@ -340,7 +334,14 @@ public:
std::string value = i->second;
infostream<<"Adding \""<<name<<"\" = \""<<value<<"\""
<<std::endl;
- os<<name<<" = "<<value<<"\n";
+ ss<<name<<" = "<<value<<"\n";
+ }
+
+ if(!fs::safeWriteToFile(filename, ss.str()))
+ {
+ errorstream<<"Error writing configuration file: \""
+ <<filename<<"\""<<std::endl;
+ return false;
}
}
diff --git a/src/subgame.cpp b/src/subgame.cpp
index 7fee3899d..806d65934 100644
--- a/src/subgame.cpp
+++ b/src/subgame.cpp
@@ -241,8 +241,9 @@ bool initializeWorld(const std::string &path, const std::string &gameid)
if(!fs::PathExists(worldmt_path)){
infostream<<"Creating world.mt ("<<worldmt_path<<")"<<std::endl;
fs::CreateAllDirs(path);
- std::ofstream of(worldmt_path.c_str(), std::ios::binary);
- of<<"gameid = "<<gameid<<"\n";
+ std::ostringstream ss(std::ios_base::binary);
+ ss<<"gameid = "<<gameid<<"\n";
+ fs::safeWriteToFile(worldmt_path, ss.str());
}
return true;
}