[Scummvm-cvs-logs] scummvm-tools master -> d38124f03c543063fff891fd88102e24eb9bac96

criezy criezy at scummvm.org
Tue Nov 22 22:59:59 CET 2011


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm-tools' repo located at https://github.com/scummvm/scummvm-tools .

Summary:
d38124f03c TOOLS: Make Common::File and isDirectory() case insensitive


Commit: d38124f03c543063fff891fd88102e24eb9bac96
    https://github.com/scummvm/scummvm-tools/commit/d38124f03c543063fff891fd88102e24eb9bac96
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2011-11-22T13:25:15-08:00

Commit Message:
TOOLS: Make Common::File and isDirectory() case insensitive

This fixes some tool adding hardcoded upper case directories (e.g.
AUDIO/) to the input path to look for files when run on case
sensitive systems.

Changed paths:
    common/file.cpp
    common/file.h



diff --git a/common/file.cpp b/common/file.cpp
index c9c62a7..2faa28d 100644
--- a/common/file.cpp
+++ b/common/file.cpp
@@ -24,6 +24,8 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <assert.h>
+#include <deque>
+#include <algorithm>
 #include <sys/stat.h>   // for stat()
 #include <sys/types.h>
 #ifndef _MSC_VER
@@ -111,6 +113,10 @@ bool Filename::exists() const {
 	// This fails if we don't have permission to read the file
 	// but in most cases, that's the same thing for us.
 	FILE *f = fopen(_path.c_str(), "r");
+	if (!f) {
+		std::string fixedPath = fixPathCase(_path);
+		f = fopen(_path.c_str(), "r");
+	}
 	if (f) {
 		fclose(f);
 		return true;
@@ -236,6 +242,10 @@ void File::open(const Filename &filepath, const char *mode) {
 	close();
 
 	_file = fopen(filepath.getFullPath().c_str(), mode);
+	if (!_file) {
+		std::string fixedPath = fixPathCase(filepath.getFullPath());
+		_file = fopen(fixedPath.c_str(), mode);
+	}
 
 	FileMode m = FILEMODE_READ;
 	do {
@@ -520,7 +530,68 @@ int removeFile(const char *path) {
 
 bool isDirectory(const char *path) {
 	struct stat st;
-	return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
+	if (stat(path, &st) == 0) {
+		return S_ISDIR(st.st_mode);
+	}
+	// Try to fix the case
+	std::string fixedPath = fixPathCase(path);
+	return stat(fixedPath.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
+}
+	
+std::string fixPathCase(const std::string& originalPath) {
+	std::string result = originalPath;
+	std::deque<std::string> parts;
+	struct stat st;
+
+	// Remove the last part of the path until we get to a path that exists
+	while (stat(result.c_str(), &st) != 0) {
+		size_t slash = result.rfind('/', result.size() - 2);
+		if (slash == std::string::npos)
+			slash = result.rfind('\\', result.size() - 2);
+		if (slash == std::string::npos) {
+			parts.push_back(result);
+			result.clear();
+			break;
+		} else {
+			parts.push_back(result.substr(slash + 1));
+			result.erase(slash + 1);
+			if (slash == 0)
+				break;
+		}
+	}
+
+	// Reconstruct the path by changing the case
+	while (!parts.empty()) {
+		std::string directory = parts.back();
+		// Try first original case, then all lower case and finally all upper case
+		std::string path = result + directory;
+		if (stat(path.c_str(), &st) == 0) {
+			result = path;
+		} else {
+			std::transform(directory.begin(), directory.end(), directory.begin(), ::tolower);
+			path = result + directory;
+			if (stat(path.c_str(), &st) == 0) {
+				result = path;
+			} else {
+				std::transform(directory.begin(), directory.end(), directory.begin(), ::toupper);
+				path = result + directory;
+				if (stat(path.c_str(), &st) == 0) {
+					result = path;
+				} else {
+					// Does not exists whatever the case used.
+					// Add back all the remaining parts and return.
+					while (!parts.empty()) {
+						result += parts.back();
+						parts.pop_back();
+					}
+					return result;
+				}
+			}
+		}
+		parts.pop_back();
+	}
+
+	return result;
 }
 
 } // End of namespace Common
diff --git a/common/file.h b/common/file.h
index 2131cda..8956a63 100644
--- a/common/file.h
+++ b/common/file.h
@@ -407,6 +407,13 @@ int removeFile(const char *path);
  */
 bool isDirectory(const char *path);
 
+/**
+ * Transform the given path into an existing path if possible
+ * by changing the case of each path element to either the
+ * original case, all lower case or all upper case.
+ */
+std::string fixPathCase(const std::string& originalPath);
+
 } // End of namespace Common
 
 






More information about the Scummvm-git-logs mailing list