diff --git a/src/fileio.cpp b/src/fileio.cpp index da64e5b7f7..ba3abb21a1 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -206,10 +206,10 @@ FILE *FioFOpenFile(const char *filename) FILE *f; char buf[MAX_PATH]; - if (strrchr(filename, PATHSEPCHAR) == NULL) { - snprintf(buf, lengthof(buf), "%s%s", _paths.data_dir, filename); - } else { + if (filename[0] == PATHSEPCHAR || filename[1] == ':') { ttd_strlcpy(buf, filename, lengthof(buf)); + } else { + snprintf(buf, lengthof(buf), "%s%s", _paths.data_dir, filename); } f = fopen(buf, "rb"); @@ -264,6 +264,31 @@ void AppendPathSeparator(char *buf, size_t buflen) } } +/** + * Allocates and files a variable with the full path + * based on the given directory. + * @param dir the directory to base the path on + * @return the malloced full path + */ +char *BuildWithFullPath(const char *dir) +{ + char *dest = MallocT(MAX_PATH); + ttd_strlcpy(dest, dir, MAX_PATH); + + /* Check if absolute or relative path */ + const char *s = strchr(dest, PATHSEPCHAR); + + /* Add absolute path */ + if (s == NULL || dest != s) { + getcwd(dest, MAX_PATH); + AppendPathSeparator(dest, MAX_PATH); + ttd_strlcat(dest, dir, MAX_PATH); + } + AppendPathSeparator(dest, MAX_PATH); + + return dest; +} + #if defined(WIN32) || defined(WINCE) /** * Determine the base (personal dir and game data dir) paths @@ -307,11 +332,9 @@ void DetermineBasePaths(const char *exe) /* Change the working directory to enable doubleclicking in UIs */ ChangeWorkingDirectory(exe); - _paths.game_data_dir = MallocT(MAX_PATH); - ttd_strlcpy(_paths.game_data_dir, GAME_DATA_DIR, MAX_PATH); + _paths.game_data_dir = BuildWithFullPath(GAME_DATA_DIR); #if defined(SECOND_DATA_DIR) - _paths.second_data_dir = MallocT(MAX_PATH); - ttd_strlcpy(_paths.second_data_dir, SECOND_DATA_DIR, MAX_PATH); + _paths.second_data_dir = BuildWithFullPath(SECOND_DATA_DIR); #else _paths.second_data_dir = NULL; #endif @@ -325,23 +348,10 @@ void DetermineBasePaths(const char *exe) } _paths.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); + AppendPathSeparator(_paths.personal_dir, MAX_PATH); #else /* not defined(USE_HOMEDIR) */ - _paths.personal_dir = MallocT(MAX_PATH); - ttd_strlcpy(_paths.personal_dir, PERSONAL_DIR, MAX_PATH); - - /* check if absolute or relative path */ - const char *s = strchr(_paths.personal_dir, PATHSEPCHAR); - - /* add absolute path */ - if (s == NULL || _paths.personal_dir != s) { - getcwd(_paths.personal_dir, MAX_PATH); - AppendPathSeparator(_paths.personal_dir, MAX_PATH); - ttd_strlcat(_paths.personal_dir, PERSONAL_DIR, MAX_PATH); - } + _paths.personal_dir = BuildWithFullPath(PERSONAL_DIR); #endif /* defined(USE_HOMEDIR) */ - - AppendPathSeparator(_paths.personal_dir, MAX_PATH); - AppendPathSeparator(_paths.game_data_dir, MAX_PATH); } #endif /* defined(WIN32) || defined(WINCE) */ @@ -366,10 +376,7 @@ void DeterminePaths(const char *exe) _paths.gm_dir = str_fmt("%sgm" PATHSEP, _paths.game_data_dir); _paths.data_dir = str_fmt("%sdata" PATHSEP, _paths.game_data_dir); #if defined(CUSTOM_LANG_DIR) - /* Sets the search path for lng files to the custom one */ - _paths.lang_dir = MallocT(MAX_PATH); - ttd_strlcpy(_paths.lang_dir, CUSTOM_LANG_DIR, MAX_PATH); - AppendPathSeparator(_paths.lang_dir, MAX_PATH); + _paths.lang_dir = BuildWithFullPath(CUSTOM_LANG_DIR); #else _paths.lang_dir = str_fmt("%slang" PATHSEP, _paths.game_data_dir); #endif diff --git a/src/newgrf.cpp b/src/newgrf.cpp index f91f947d6d..3236b52c3d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -4941,7 +4941,7 @@ void LoadNewGRF(uint load_index, uint file_index) if (c->status == GCS_DISABLED || c->status == GCS_NOT_FOUND) continue; /* @todo usererror() */ - if (!FileExists(c->full_path)) error("NewGRF file is missing '%s'", c->filename); + if (!FioCheckFileExists(c->full_path)) error("NewGRF file is missing '%s'", c->filename); if (stage == GLS_LABELSCAN) InitNewGRFFile(c, _cur_spriteid); LoadNewGRFFile(c, slot++, stage); diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index 6b58074964..3e3cfdc526 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -40,7 +40,7 @@ static bool CalcGRFMD5Sum(GRFConfig *config) size_t len; /* open the file */ - f = fopen(config->full_path, "rb"); + f = FioFOpenFile(config->full_path); if (f == NULL) return false; /* calculate md5sum */ @@ -59,13 +59,14 @@ static bool CalcGRFMD5Sum(GRFConfig *config) /* Find the GRFID and calculate the md5sum */ bool FillGRFDetails(GRFConfig *config, bool is_static) { - if (!FileExists(config->full_path)) { + if (!FioCheckFileExists(config->full_path)) { config->status = GCS_NOT_FOUND; return false; } if (config->filename == NULL) { - config->filename = strdup(strrchr(config->full_path, PATHSEPCHAR) + 1); + const char *t = strrchr(config->full_path, PATHSEPCHAR); + config->filename = strdup(t != NULL ? t + 1 : config->full_path); } /* Find and load the Action 8 information */ @@ -278,7 +279,7 @@ compatible_grf: extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb); /* Scan a path for NewGRFs */ -static uint ScanPath(const char *path) +static uint ScanPath(const char *path, int basepath_length) { uint num = 0; struct stat sb; @@ -299,7 +300,7 @@ static uint ScanPath(const char *path) /* Directory */ if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue; AppendPathSeparator(filename, lengthof(filename)); - num += ScanPath(filename); + num += ScanPath(filename, basepath_length); } else if (sb.st_mode & S_IFREG) { /* File */ char *ext = strrchr(filename, '.'); @@ -309,7 +310,7 @@ static uint ScanPath(const char *path) if (strcasecmp(ext, ".grf") != 0) continue; GRFConfig *c = CallocT(1); - c->full_path = strdup(filename); + c->full_path = strdup(filename + basepath_length); bool added = true; if (FillGRFDetails(c, false)) { @@ -360,8 +361,10 @@ void ScanNewGRFFiles() ClearGRFConfigList(&_all_grfs); DEBUG(grf, 1, "Scanning for NewGRFs"); - num = ScanPath(_paths.data_dir); - num += ScanPath(_paths.second_data_dir); + num = ScanPath(_paths.data_dir, strlen(_paths.data_dir)); + if (_paths.second_data_dir != NULL) { + num += ScanPath(_paths.second_data_dir, strlen(_paths.second_data_dir)); + } DEBUG(grf, 1, "Scan complete, found %d files", num); } diff --git a/src/stdafx.h b/src/stdafx.h index 94c6da5ffe..a25789ecad 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -196,6 +196,7 @@ * call to the same function and is not thread- or reentrancy-safe */ #if !defined(STRGEN) # if defined(WIN32) || defined(WIN64) +char *getcwd(char *buf, size_t size); # include /* XXX - WinCE without MSVCRT doesn't support wfopen, so it seems */ # if !defined(WINCE) diff --git a/src/win32.cpp b/src/win32.cpp index 4d99536d1e..fc119ce8ed 100644 --- a/src/win32.cpp +++ b/src/win32.cpp @@ -946,16 +946,30 @@ void GetCurrentDirectoryW(int length, wchar_t *path) } #endif -void DetermineBasePaths(const char *exe) +char *getcwd(char *buf, size_t size) { - _paths.personal_dir = _paths.game_data_dir = MallocT(MAX_PATH); - _paths.second_data_dir = NULL; #if defined(UNICODE) TCHAR path[MAX_PATH]; GetCurrentDirectory(MAX_PATH - 1, path); - convert_from_fs(path, _paths.personal_dir, MAX_PATH); + convert_from_fs(path, buf, size); #else - GetCurrentDirectory(MAX_PATH - 1, _paths.personal_dir); + GetCurrentDirectory(size, buf); +#endif + return buf; +} + +extern char *BuildWithFullPath(const char *dir); + +void DetermineBasePaths(const char *exe) +{ + _paths.personal_dir = MallocT(MAX_PATH); + getcwd(_paths.personal_dir, MAX_PATH); + + _paths.game_data_dir = BuildWithFullPath(GAME_DATA_DIR); +#if defined(SECOND_DATA_DIR) + _paths.second_data_dir = BuildWithFullPath(SECOND_DATA_DIR); +#else + _paths.second_data_dir = NULL; #endif _paths.personal_dir[0] = toupper(_paths.personal_dir[0]);