diff --git a/src/fileio.cpp b/src/fileio.cpp --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -10,6 +10,10 @@ #include "macros.h" #include "variables.h" #include "debug.h" +#include "fios.h" +#ifndef WIN32 +#include +#endif /*************************************************/ /* FILE IO ROUTINES ******************************/ @@ -211,3 +215,82 @@ void FioOpenFile(int slot, const char *f #endif /* LIMITED_FDS */ FioSeekToFile(slot << 24); } + +/** + * Create a directory with the given name + * @param name the new name of the directory + */ +void FioCreateDirectory(const char *name) +{ +#if defined(WIN32) || defined(WINCE) + CreateDirectory(OTTD2FS(name), NULL); +#elif defined(OS2) && !defined(__INNOTEK_LIBC__) + mkdir(OTTD2FS(name)); +#else + mkdir(OTTD2FS(name), 0755); +#endif +} + +/** + * Appends, if necessary, the path separator character to the end of the string. + * It does not add the path separator to zero-sized strings. + * @param buf string to append the separator to + * @param buflen the length of the buf + */ +void AppendPathSeparator(char *buf, size_t buflen) +{ + size_t s = strlen(buf); + + /* Length of string + path separator + '\0' */ + if (s != 0 && buf[s - 1] != PATHSEPCHAR && s + 2 < buflen) { + buf[s] = PATHSEPCHAR; + buf[s + 1] = '\0'; + } +} + +/** + * Determine the base (personal dir and game data dir) paths + * @note defined in the OS related files (os2.cpp, win32.cpp, unix.cpp etc) + */ +extern void DetermineBasePaths(); + +/** + * Acquire the base paths (personal dir and game data dir), + * fill all other paths (save dir, autosave dir etc) and + * make the save and scenario directories. + * @todo for save_dir, autosave_dir, scenario_dir and heightmap_dir the + * assumption is that there is no path separator, however for gm_dir + * lang_dir and data_dir that assumption is made. + * This inconsistency should be resolved. + */ +void DeterminePaths() +{ + DetermineBasePaths(); + + _paths.save_dir = str_fmt("%ssave", _paths.personal_dir); + _paths.autosave_dir = str_fmt("%s" PATHSEP "autosave", _paths.save_dir); + _paths.scenario_dir = str_fmt("%sscenario", _paths.personal_dir); + _paths.heightmap_dir = str_fmt("%s" PATHSEP "heightmap", _paths.heightmap_dir); + _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); +#else + _paths.lang_dir = str_fmt("%slang" PATHSEP, _paths.game_data_dir); +#endif + + if (_config_file == NULL) { + _config_file = str_fmt("%sopenttd.cfg", _paths.personal_dir); + } + + _highscore_file = str_fmt("%shs.dat", _paths.personal_dir); + _log_file = str_fmt("%sopenttd.log", _paths.personal_dir); + + /* Make (auto)save and scenario folder */ + FioCreateDirectory(_paths.save_dir); + FioCreateDirectory(_paths.autosave_dir); + FioCreateDirectory(_paths.scenario_dir); + FioCreateDirectory(_paths.heightmap_dir); +} diff --git a/src/fileio.h b/src/fileio.h --- a/src/fileio.h +++ b/src/fileio.h @@ -12,10 +12,15 @@ byte FioReadByte(); uint16 FioReadWord(); uint32 FioReadDword(); void FioCloseAll(); -FILE *FioFOpenFile(const char *filename); void FioOpenFile(int slot, const char *filename); void FioReadBlock(void *ptr, uint size); void FioSkipBytes(int n); + +FILE *FioFOpenFile(const char *filename); bool FioCheckFileExists(const char *filename); +void FioCreateDirectory(const char *filename); + +void AppendPathSeparator(char *buf, size_t buflen); +void DeterminePaths(); #endif /* FILEIO_H */ diff --git a/src/functions.h b/src/functions.h --- a/src/functions.h +++ b/src/functions.h @@ -216,6 +216,4 @@ void CheckConfig(); int ttd_main(int argc, char* argv[]); void HandleExitGameRequest(); -void DeterminePaths(); - #endif /* FUNCTIONS_H */ diff --git a/src/os2.cpp b/src/os2.cpp --- a/src/os2.cpp +++ b/src/os2.cpp @@ -9,7 +9,7 @@ #include "gui.h" #include "functions.h" #include "macros.h" -#include "fios.h" +#include "fileio.h" #include #include @@ -178,87 +178,41 @@ int CDECL main(int argc, char* argv[]) return ttd_main(argc, argv); } -void DeterminePaths() +void DetermineBasePaths() { - char *s; - - _paths.game_data_dir = (char *)malloc(MAX_PATH); + _paths.game_data_dir = MallocT(MAX_PATH); ttd_strlcpy(_paths.game_data_dir, GAME_DATA_DIR, MAX_PATH); -#if defined SECOND_DATA_DIR - _paths.second_data_dir = malloc(MAX_PATH); +#if defined(SECOND_DATA_DIR) + _paths.second_data_dir = MallocT(MAX_PATH); ttd_strlcpy(_paths.second_data_dir, SECOND_DATA_DIR, MAX_PATH); #endif #if defined(USE_HOMEDIR) - { - const char *homedir = getenv("HOME"); + const char *homedir = getenv("HOME"); - if (homedir == NULL) { - const struct passwd *pw = getpwuid(getuid()); - if (pw != NULL) homedir = pw->pw_dir; - } - - _paths.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); + if (homedir == NULL) { + const struct passwd *pw = getpwuid(getuid()); + if (pw != NULL) homedir = pw->pw_dir; } + _paths.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); #else /* not defined(USE_HOMEDIR) */ - - _paths.personal_dir = (char *)malloc(MAX_PATH); + _paths.personal_dir = MallocT(MAX_PATH); ttd_strlcpy(_paths.personal_dir, PERSONAL_DIR, MAX_PATH); - // check if absolute or relative path - s = strchr(_paths.personal_dir, PATHSEPCHAR); + /* check if absolute or relative path */ + const char *s = strchr(_paths.personal_dir, PATHSEPCHAR); - // add absolute path + /* add absolute path */ if (s == NULL || _paths.personal_dir != s) { getcwd(_paths.personal_dir, MAX_PATH); - s = strchr(_paths.personal_dir, 0); - *s++ = PATHSEPCHAR; - ttd_strlcpy(s, PERSONAL_DIR, MAX_PATH); + AppendPathSeparator(_paths.personal_dir, MAX_PATH); + ttd_strlcat(_paths.personal_dir, PERSONAL_DIR, MAX_PATH); } - #endif /* defined(USE_HOMEDIR) */ - s = strchr(_paths.personal_dir, 0); - - // append a / ? - if (s[-1] != PATHSEPCHAR) strcpy(s, PATHSEP); - - _paths.save_dir = str_fmt("%ssave", _paths.personal_dir); - _paths.autosave_dir = str_fmt("%s" PATHSEP "autosave", _paths.save_dir); - _paths.scenario_dir = str_fmt("%sscenario", _paths.personal_dir); - _paths.heightmap_dir = str_fmt("%sscenario" PATHSEP "heightmap", _paths.personal_dir); - _paths.gm_dir = str_fmt("%sgm" PATHSEP, _paths.game_data_dir); - _paths.data_dir = str_fmt("%sdata" PATHSEP, _paths.game_data_dir); - - if (_config_file == NULL) - _config_file = str_fmt("%sopenttd.cfg", _paths.personal_dir); - - _highscore_file = str_fmt("%shs.dat", _paths.personal_dir); - _log_file = str_fmt("%sopenttd.log", _paths.personal_dir); - -#if defined CUSTOM_LANG_DIR - // sets the search path for lng files to the custom one - _paths.lang_dir = malloc( MAX_PATH ); - ttd_strlcpy( _paths.lang_dir, CUSTOM_LANG_DIR, MAX_PATH); -#else - _paths.lang_dir = str_fmt("%slang" PATHSEP, _paths.game_data_dir); -#endif - - // create necessary folders -#ifndef __INNOTEK_LIBC__ - mkdir(_paths.personal_dir); - mkdir(_paths.save_dir); - mkdir(_paths.autosave_dir); - mkdir(_paths.scenario_dir); - mkdir(_paths.heightmap_dir); -#else - mkdir(_paths.personal_dir, 0755); - mkdir(_paths.save_dir, 0755); - mkdir(_paths.autosave_dir, 0755); - mkdir(_paths.scenario_dir, 0755); - mkdir(_paths.heightmap_dir, 0755); -#endif + AppendPathSeparator(_paths.personal_dir, MAX_PATH); + AppendPathSeparator(_paths.game_data_dir, MAX_PATH); } /** diff --git a/src/unix.cpp b/src/unix.cpp --- a/src/unix.cpp +++ b/src/unix.cpp @@ -7,6 +7,7 @@ #include "string.h" #include "table/strings.h" #include "variables.h" +#include "fileio.h" #include #include @@ -168,79 +169,41 @@ int CDECL main(int argc, char* argv[]) return ret; } -void DeterminePaths() +void DetermineBasePaths() { - char *s; - _paths.game_data_dir = MallocT(MAX_PATH); ttd_strlcpy(_paths.game_data_dir, GAME_DATA_DIR, MAX_PATH); - #if defined SECOND_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); - #endif +#endif #if defined(USE_HOMEDIR) - { - const char *homedir = getenv("HOME"); + const char *homedir = getenv("HOME"); - if (homedir == NULL) { - const struct passwd *pw = getpwuid(getuid()); - if (pw != NULL) homedir = pw->pw_dir; - } - - _paths.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); + if (homedir == NULL) { + const struct passwd *pw = getpwuid(getuid()); + if (pw != NULL) homedir = pw->pw_dir; } + _paths.personal_dir = str_fmt("%s" PATHSEP "%s", homedir, PERSONAL_DIR); #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 - s = strchr(_paths.personal_dir, '/'); + /* check if absolute or relative path */ + const char *s = strchr(_paths.personal_dir, PATHSEPCHAR); - // add absolute path + /* add absolute path */ if (s == NULL || _paths.personal_dir != s) { getcwd(_paths.personal_dir, MAX_PATH); - s = strchr(_paths.personal_dir, 0); - *s++ = '/'; - ttd_strlcpy(s, PERSONAL_DIR, MAX_PATH); + AppendPathSeparator(_paths.personal_dir, MAX_PATH); + ttd_strlcat(_paths.personal_dir, PERSONAL_DIR, MAX_PATH); } - #endif /* defined(USE_HOMEDIR) */ - s = strchr(_paths.personal_dir, 0); - - // append a / ? - if (s[-1] != '/') strcpy(s, "/"); - - _paths.save_dir = str_fmt("%ssave", _paths.personal_dir); - _paths.autosave_dir = str_fmt("%s/autosave", _paths.save_dir); - _paths.scenario_dir = str_fmt("%sscenario", _paths.personal_dir); - _paths.heightmap_dir = str_fmt("%sscenario/heightmap", _paths.personal_dir); - _paths.gm_dir = str_fmt("%sgm/", _paths.game_data_dir); - _paths.data_dir = str_fmt("%sdata/", _paths.game_data_dir); - - if (_config_file == NULL) - _config_file = str_fmt("%sopenttd.cfg", _paths.personal_dir); - - _highscore_file = str_fmt("%shs.dat", _paths.personal_dir); - _log_file = str_fmt("%sopenttd.log", _paths.personal_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); -#else - _paths.lang_dir = str_fmt("%slang/", _paths.game_data_dir); -#endif - - // create necessary folders - mkdir(_paths.personal_dir, 0755); - mkdir(_paths.save_dir, 0755); - mkdir(_paths.autosave_dir, 0755); - mkdir(_paths.scenario_dir, 0755); - mkdir(_paths.heightmap_dir, 0755); + AppendPathSeparator(_paths.personal_dir, MAX_PATH); + AppendPathSeparator(_paths.game_data_dir, MAX_PATH); } bool InsertTextBufferClipboard(Textbuf *tb) diff --git a/src/win32.cpp b/src/win32.cpp --- a/src/win32.cpp +++ b/src/win32.cpp @@ -13,6 +13,7 @@ #include "string.h" #include "gfx.h" #include "window.h" +#include "fileio.h" #include #include #include @@ -942,42 +943,19 @@ void GetCurrentDirectoryW(int length, wc } #endif -void DeterminePaths() +void DetermineBasePaths() { - char *s, *cfg; - - _paths.personal_dir = _paths.game_data_dir = cfg = (char*)malloc(MAX_PATH); + _paths.personal_dir = _paths.game_data_dir = MallocT(MAX_PATH); #if defined(UNICODE) TCHAR path[MAX_PATH]; GetCurrentDirectory(MAX_PATH - 1, path); - convert_from_fs(path, cfg, MAX_PATH); + convert_from_fs(path, _paths.personal_dir, MAX_PATH); #else - GetCurrentDirectory(MAX_PATH - 1, cfg); + GetCurrentDirectory(MAX_PATH - 1, _paths.personal_dir); #endif - cfg[0] = toupper(cfg[0]); - s = strchr(cfg, '\0'); - if (s[-1] != '\\') strcpy(s, "\\"); - - _paths.save_dir = str_fmt("%ssave", cfg); - _paths.autosave_dir = str_fmt("%s\\autosave", _paths.save_dir); - _paths.scenario_dir = str_fmt("%sscenario", cfg); - _paths.heightmap_dir = str_fmt("%sscenario\\heightmap", cfg); - _paths.gm_dir = str_fmt("%sgm\\", cfg); - _paths.data_dir = str_fmt("%sdata\\", cfg); - _paths.lang_dir = str_fmt("%slang\\", cfg); - - if (_config_file == NULL) - _config_file = str_fmt("%sopenttd.cfg", _paths.personal_dir); - - _highscore_file = str_fmt("%shs.dat", _paths.personal_dir); - _log_file = str_fmt("%sopenttd.log", _paths.personal_dir); - - // make (auto)save and scenario folder - CreateDirectory(OTTD2FS(_paths.save_dir), NULL); - CreateDirectory(OTTD2FS(_paths.autosave_dir), NULL); - CreateDirectory(OTTD2FS(_paths.scenario_dir), NULL); - CreateDirectory(OTTD2FS(_paths.heightmap_dir), NULL); + _paths.personal_dir[0] = toupper(_paths.personal_dir[0]); + AppendPathSeparator(_paths.personal_dir, MAX_PATH); } /**