← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/fix-lan-autosave into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/fix-lan-autosave into lp:widelands.

Commit message:
Fixed crash with identical autosave filenames when LAN game is run with multiple instances of Widelands on a single computer. Also, more informative error messages in disk_filesystem.cc.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/fix-lan-autosave/+merge/286071

Fixed crash with identical autosave filenames when LAN game is run with multiple instances of Widelands on a single computer. Also, more informative error messages in disk_filesystem.cc.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/fix-lan-autosave into lp:widelands.
=== modified file 'src/io/filesystem/disk_filesystem.cc'
--- src/io/filesystem/disk_filesystem.cc	2016-01-10 13:22:20 +0000
+++ src/io/filesystem/disk_filesystem.cc	2016-02-15 15:23:38 +0000
@@ -51,16 +51,16 @@
 
 struct FileSystemPath: public std::string
 {
-	bool m_exists;
-	bool m_isDirectory;
+	bool exists_;
+	bool is_directory_;
 
 	FileSystemPath(const std::string & path)
 	: std::string(path)
 	{
 		struct stat st;
 
-		m_exists = (stat(c_str(), &st) != -1);
-		m_isDirectory = m_exists && S_ISDIR(st.st_mode);
+		exists_ = (stat(c_str(), &st) != -1);
+		is_directory_ = exists_ && S_ISDIR(st.st_mode);
 	}
 };
 
@@ -68,10 +68,10 @@
  * Initialize the real file-system
  */
 RealFSImpl::RealFSImpl(const std::string & Directory)
-: m_directory(Directory)
+: directory_(Directory)
 {
 	// TODO(unknown): check OS permissions on whether the directory is writable!
-	m_root = canonicalize_name(Directory);
+	root_ = canonicalize_name(Directory);
 }
 
 
@@ -105,9 +105,9 @@
 	long hFile;
 
 	if (path.size())
-		buf = m_directory + '\\' + path + "\\*";
+		buf = directory_ + '\\' + path + "\\*";
 	else
-		buf = m_directory + "\\*";
+		buf = directory_ + "\\*";
 
 	std::set<std::string> results;
 
@@ -145,12 +145,12 @@
 			buf = path + "/*";
 			ofs = 0;
 		} else {
-			buf = m_directory + '/' + path + "/*";
-			ofs = m_directory.length() + 1;
+			buf = directory_ + '/' + path + "/*";
+			ofs = directory_.length() + 1;
 		}
 	} else {
-		buf = m_directory + "/*";
-		ofs = m_directory.length() + 1;
+		buf = directory_ + "/*";
+		ofs = directory_.length() + 1;
 	}
 	std::set<std::string> results;
 
@@ -159,7 +159,7 @@
 
 	for (size_t i = 0; i < gl.gl_pathc; ++i) {
 		const std::string filename(canonicalize_name(&gl.gl_pathv[i][ofs]));
-		results.insert(filename.substr(m_root.size() + 1));
+		results.insert(filename.substr(root_.size() + 1));
 	}
 
 	globfree(&gl);
@@ -175,7 +175,7 @@
  */
 // TODO(unknown): Can this be rewritten to just using exceptions? Should it?
 bool RealFSImpl::file_exists(const std::string & path) {
-	return FileSystemPath(canonicalize_name(path)).m_exists;
+	return FileSystemPath(canonicalize_name(path)).exists_;
 }
 
 /**
@@ -184,7 +184,7 @@
  * \e can't exist then)
  */
 bool RealFSImpl::is_directory(const std::string & path) {
-	return FileSystemPath(canonicalize_name(path)).m_isDirectory;
+	return FileSystemPath(canonicalize_name(path)).is_directory_;
 }
 
 /**
@@ -192,9 +192,14 @@
  */
 FileSystem * RealFSImpl::make_sub_file_system(const std::string & path) {
 	FileSystemPath fspath(canonicalize_name(path));
-	assert(fspath.m_exists); //TODO(unknown): throw an exception instead
-
-	if (fspath.m_isDirectory)
+
+	if (!fspath.exists_) {
+		throw wexception("RealFSImpl: unable to create sub filesystem, path does not exist for '%s'"
+							  " in directory '%s'",
+							  fspath.c_str(), directory_.c_str());
+	}
+
+	if (fspath.is_directory_)
 		return new RealFSImpl   (fspath);
 	else
 		return new ZipFilesystem(fspath);
@@ -206,10 +211,10 @@
 FileSystem * RealFSImpl::create_sub_file_system(const std::string & path, Type const fs)
 {
 	FileSystemPath fspath(canonicalize_name(path));
-	if (fspath.m_exists)
+	if (fspath.exists_)
 		throw wexception
-			("path %s already exists, can not create a filesystem from it",
-			 path.c_str());
+			("path '%s'' already exists in directory '%s', can not create a filesystem from it",
+			 path.c_str(), directory_.c_str());
 
 	if (fs == FileSystem::DIR) {
 		ensure_directory_exists(path);
@@ -223,22 +228,28 @@
  */
 void RealFSImpl::fs_unlink(const std::string & file) {
 	FileSystemPath fspath(canonicalize_name(file));
-	if (!fspath.m_exists)
+	if (!fspath.exists_)
 		return;
 
-	if (fspath.m_isDirectory)
-		m_unlink_directory(file);
+	if (fspath.is_directory_)
+		unlink_directory(file);
 	else
-		m_unlink_file(file);
+		unlink_file(file);
 }
 
 /**
  * Remove a single directory or file
  */
-void RealFSImpl::m_unlink_file(const std::string & file) {
+void RealFSImpl::unlink_file(const std::string & file) {
 	FileSystemPath fspath(canonicalize_name(file));
-	assert(fspath.m_exists);  //TODO(unknown): throw an exception instead
-	assert(!fspath.m_isDirectory); //TODO(unknown): throw an exception instead
+	if (!fspath.exists_) {
+		throw wexception("RealFSImpl: unable to unlink file, path does not exist for '%s' in directory '%s'",
+							  fspath.c_str(), directory_.c_str());
+	}
+	if (fspath.is_directory_) {
+		throw wexception("RealFSImpl: unable to unlink file, path '%s' in directory '%s' is a directory",
+							  fspath.c_str(), directory_.c_str());
+	}
 
 #ifndef _WIN32
 	unlink(fspath.c_str());
@@ -250,10 +261,17 @@
 /**
  * Recursively remove a directory
  */
-void RealFSImpl::m_unlink_directory(const std::string & file) {
+void RealFSImpl::unlink_directory(const std::string & file) {
 	FileSystemPath fspath(canonicalize_name(file));
-	assert(fspath.m_exists);  //TODO(unknown): throw an exception instead
-	assert(fspath.m_isDirectory);  //TODO(unknown): throw an exception instead
+	if (!fspath.exists_) {
+		throw wexception("RealFSImpl: unable to unlink directory, path does not exist for '%s'"
+							  " in directory '%s'",
+							  fspath.c_str(), directory_.c_str());
+	}
+	if (!fspath.is_directory_) {
+		throw wexception("RealFSImpl: unable to unlink directoy, path '%s' in directory '%s'"
+							  " is not a directory", fspath.c_str(), directory_.c_str());
+	}
 
 	FilenameSet files = list_directory(file);
 	for
@@ -268,9 +286,9 @@
 			continue;
 
 		if (is_directory(*pname))
-			m_unlink_directory(*pname);
+			unlink_directory(*pname);
 		else
-			m_unlink_file(*pname);
+			unlink_file(*pname);
 	}
 
 	// NOTE: this might fail if this directory contains CVS dir,
@@ -279,7 +297,7 @@
 	rmdir(fspath.c_str());
 #else
 	if (!RemoveDirectory(fspath.c_str()))
-		throw wexception("%s could not be deleted.", fspath.c_str());
+		throw wexception("'%s' could not be deleted in directory '%s'.", fspath.c_str(), directory_.c_str());
 #endif
 }
 
@@ -295,11 +313,11 @@
 			it = dirname.find(file_separator(), it);
 
 			FileSystemPath fspath(canonicalize_name(dirname.substr(0, it)));
-			if (fspath.m_exists && !fspath.m_isDirectory)
+			if (fspath.exists_ && !fspath.is_directory_)
 				throw wexception
-					("%s exists and is not a directory",
-					 dirname.substr(0, it).c_str());
-			if (!fspath.m_exists)
+					("'%s' in directory '%s' exists and is not a directory",
+					 dirname.substr(0, it).c_str(), directory_.c_str());
+			if (!fspath.exists_)
 				make_directory(dirname.substr(0, it));
 
 			if (it == std::string::npos)
@@ -308,8 +326,8 @@
 		}
 	} catch (const std::exception & e) {
 		throw wexception
-			("RealFSImpl::ensure_directory_exists(%s): %s",
-			 dirname.c_str(), e.what());
+			("RealFSImpl::ensure_directory_exists(%s) in directory '%s': %s",
+			 dirname.c_str(), directory_.c_str(), e.what());
 	}
 }
 
@@ -323,9 +341,10 @@
  */
 void RealFSImpl::make_directory(const std::string & dirname) {
 	FileSystemPath fspath(canonicalize_name(dirname));
-	if (fspath.m_exists)
+	if (fspath.exists_)
 		throw wexception
-			("a file with the name \"%s\" already exists", dirname.c_str());
+			("a file/directory with the name '%s' already exists in directory '%s'",
+			 dirname.c_str(), directory_.c_str());
 
 	if
 #ifdef _WIN32
@@ -442,28 +461,28 @@
 
 struct RealFSStreamRead : public StreamRead {
 	RealFSStreamRead(const std::string & fname)
-		: m_file(fopen(fname.c_str(), "rb"))
+		: file_(fopen(fname.c_str(), "rb"))
 	{
-		if (!m_file)
+		if (!file_)
 			throw wexception("could not open %s for reading", fname.c_str());
 	}
 
 	~RealFSStreamRead()
 	{
-		fclose(m_file);
+		fclose(file_);
 	}
 
 	size_t data(void * read_data, size_t const bufsize) override {
-		return fread(read_data, 1, bufsize, m_file);
+		return fread(read_data, 1, bufsize, file_);
 	}
 
 	bool end_of_file() const override
 	{
-		return feof(m_file);
+		return feof(file_);
 	}
 
 private:
-	FILE * m_file;
+	FILE * file_;
 };
 
 }
@@ -485,31 +504,31 @@
 
 struct RealFSStreamWrite : public StreamWrite {
 	RealFSStreamWrite(const std::string & fname)
-		: m_filename(fname)
+		: filename_(fname)
 	{
-		m_file = fopen(fname.c_str(), "wb");
-		if (!m_file)
+		file_ = fopen(fname.c_str(), "wb");
+		if (!file_)
 			throw wexception("could not open %s for writing", fname.c_str());
 	}
 
-	~RealFSStreamWrite() {fclose(m_file);}
+	~RealFSStreamWrite() {fclose(file_);}
 
 	void data(const void * const write_data, const size_t size) override
 	{
-		size_t ret = fwrite(write_data, 1, size, m_file);
+		size_t ret = fwrite(write_data, 1, size, file_);
 
 		if (ret != size)
-			throw wexception("Write to %s failed", m_filename.c_str());
+			throw wexception("Write to %s failed", filename_.c_str());
 	}
 
 	void flush() override
 	{
-		fflush(m_file);
+		fflush(file_);
 	}
 
 private:
-	std::string m_filename;
-	FILE * m_file;
+	std::string filename_;
+	FILE * file_;
 };
 
 }
@@ -525,14 +544,14 @@
 	ULARGE_INTEGER freeavailable;
 	return
 		GetDiskFreeSpaceEx
-			(canonicalize_name(m_directory).c_str(), &freeavailable, 0, 0)
+			(canonicalize_name(directory_).c_str(), &freeavailable, 0, 0)
 		?
 		//if more than 2G free space report that much
 		freeavailable.HighPart ? std::numeric_limits<unsigned long>::max() :
 		freeavailable.LowPart : 0;
 #else
 	struct statvfs svfs;
-	if (statvfs(canonicalize_name(m_directory).c_str(), &svfs) != -1) {
+	if (statvfs(canonicalize_name(directory_).c_str(), &svfs) != -1) {
 		return static_cast<unsigned long long>(svfs.f_bsize) * svfs.f_bavail;
 	}
 #endif

=== modified file 'src/io/filesystem/disk_filesystem.h'
--- src/io/filesystem/disk_filesystem.h	2014-09-29 13:30:46 +0000
+++ src/io/filesystem/disk_filesystem.h	2016-02-15 15:23:38 +0000
@@ -54,14 +54,14 @@
 	void fs_unlink(const std::string & file) override;
 	void fs_rename(const std::string & old_name, const std::string & new_name) override;
 
-	std::string get_basename() override {return m_directory;}
+	std::string get_basename() override {return directory_;}
 	unsigned long long disk_space() override;
 
 private:
-	void m_unlink_directory(const std::string & file);
-	void m_unlink_file     (const std::string & file);
+	void unlink_directory(const std::string & file);
+	void unlink_file     (const std::string & file);
 
-	std::string m_directory;
+	std::string directory_;
 };
 
 #endif  // end of include guard: WL_IO_FILESYSTEM_DISK_FILESYSTEM_H

=== modified file 'src/io/filesystem/filesystem.cc'
--- src/io/filesystem/filesystem.cc	2014-12-03 07:15:40 +0000
+++ src/io/filesystem/filesystem.cc	2016-02-15 15:23:38 +0000
@@ -62,7 +62,7 @@
 
 FileSystem::FileSystem()
 {
-	m_root = "";
+	root_ = "";
 }
 
 
@@ -72,15 +72,15 @@
  */
 bool FileSystem::is_path_absolute(const std::string & path) const {
 	std::string::size_type const path_size = path  .size();
-	std::string::size_type const root_size = m_root.size();
+	std::string::size_type const root_size = root_.size();
 
 	if (path_size < root_size)
 		return false;
 
 	if (path_size == root_size)
-		return path == m_root;
+		return path == root_;
 
-	if (path.compare(0, m_root.size(), m_root))
+	if (path.compare(0, root_.size(), root_))
 		return false;
 
 #ifdef _WIN32
@@ -262,7 +262,7 @@
 	} else if (!is_path_absolute(path))
 		//  make relative paths absolute (so that "../../foo" can work)
 		fs_tokenize
-			(m_root.empty() ? get_working_directory() : m_root, file_separator(),
+			(root_.empty() ? get_working_directory() : root_, file_separator(),
 			 std::inserter(components, components.begin()));
 
 	//clean up the path

=== modified file 'src/io/filesystem/filesystem.h'
--- src/io/filesystem/filesystem.h	2016-02-06 18:58:57 +0000
+++ src/io/filesystem/filesystem.h	2016-02-15 15:23:38 +0000
@@ -142,7 +142,7 @@
 
 	///How to address the fs' topmost component (e.g. "" on Unix, "D:" on win32)
 	///\warning This is should \e not contain filesep!
-	std::string m_root;
+	std::string root_;
 
 #ifdef _WIN32
 private:

=== modified file 'src/logic/save_handler.cc'
--- src/logic/save_handler.cc	2015-11-14 15:58:29 +0000
+++ src/logic/save_handler.cc	2016-02-15 15:23:38 +0000
@@ -44,7 +44,7 @@
 void SaveHandler::think(Widelands::Game & game) {
 	uint32_t realtime = SDL_GetTicks();
 	initialize(realtime);
-	std::string filename = "wl_autosave";
+	std::string filename = autosave_filename_;
 
 	if (!m_allow_saving) {
 		return;
@@ -97,7 +97,7 @@
 			filename_previous = filename_next;
 			number_of_rolls--;
 		}
-		filename = "wl_autosave_00";
+		filename = (boost::format("%s_00") % autosave_filename_).str();
 		log("Autosave: interval elapsed (%d s), saving %s\n", elapsed, filename.c_str());
 	}
 

=== modified file 'src/logic/save_handler.h'
--- src/logic/save_handler.h	2015-11-14 15:58:29 +0000
+++ src/logic/save_handler.h	2016-02-15 15:23:38 +0000
@@ -33,7 +33,7 @@
 class SaveHandler {
 public:
 	SaveHandler() : m_last_saved_realtime(0), m_initialized(false), m_allow_saving(true),
-		m_save_requested(false), m_save_filename("") {}
+		m_save_requested(false), m_save_filename(""), autosave_filename_("wl_autosave") {}
 	void think(Widelands::Game &);
 	std::string create_file_name(std::string dir, std::string filename);
 	bool save_game
@@ -44,6 +44,7 @@
 	static std::string get_base_dir() {return "save";}
 	const std::string get_cur_filename() {return m_current_filename;}
 	void set_current_filename(std::string filename) {m_current_filename = filename;}
+	void set_autosave_filename(std::string filename) {autosave_filename_ = filename;}
 	void set_allow_saving(bool t) {m_allow_saving = t;}
 	bool get_allow_saving() {return m_allow_saving;}
 	void request_save(std::string filename = "")
@@ -59,6 +60,7 @@
 	bool m_save_requested;
 	std::string m_save_filename;
 	std::string m_current_filename;
+	std::string autosave_filename_;
 
 	void initialize(uint32_t gametime);
 };

=== modified file 'src/network/netclient.cc'
--- src/network/netclient.cc	2016-02-15 15:04:34 +0000
+++ src/network/netclient.cc	2016-02-15 15:23:38 +0000
@@ -186,6 +186,7 @@
 		d->game = &game;
 		game.set_game_controller(this);
 		uint8_t const pn = d->settings.playernum + 1;
+		game.save_handler().set_autosave_filename((boost::format("wl_autosave_netclient%u") % static_cast<unsigned int>(pn)).str());
 		InteractiveGameBase* igb;
 		if (pn > 0)
 			igb = new InteractivePlayer(game, g_options.pull_section("global"), pn, true);

=== modified file 'src/network/nethost.cc'
--- src/network/nethost.cc	2016-02-15 15:04:34 +0000
+++ src/network/nethost.cc	2016-02-15 15:23:38 +0000
@@ -730,6 +730,7 @@
 		game.set_game_controller(this);
 		InteractiveGameBase* igb;
 		uint8_t pn = d->settings.playernum + 1;
+		game.save_handler().set_autosave_filename("wl_autosave_nethost");
 
 		if (d->settings.savegame) {
 			// Read and broadcast original win condition


Follow ups