18 # define access _taccess 19 #elif defined(__HAIKU__) 21 #include <storage/FindDirectory.h> 30 #ifdef WITH_XDG_BASEDIR 37 #define FIO_BUFFER_SIZE 512 49 #if defined(LIMITED_FDS) 92 if (fseek(_fio.
cur_fh, _fio.
pos, SEEK_SET) < 0) {
97 #if defined(LIMITED_FDS) 98 static void FioRestoreFile(
int slot)
101 if (_fio.
handles[slot] ==
nullptr) {
102 DEBUG(misc, 6,
"Restoring file '%s' in slot '%d' from disk", _fio.
filenames[slot], slot);
105 _fio.usage_count[slot]++;
117 #if defined(LIMITED_FDS) 119 FioRestoreFile(slot);
122 assert(f !=
nullptr);
140 if (size == 0)
return 0;
142 return *_fio.buffer++;
189 _fio.
pos += fread(ptr, 1, size, _fio.
cur_fh);
198 if (_fio.
handles[slot] !=
nullptr) {
205 #if defined(LIMITED_FDS) 219 #if defined(LIMITED_FDS) 220 static void FioFreeHandle()
223 if (_fio.open_handles + 1 == LIMITED_FDS) {
231 if (_fio.
handles[i] !=
nullptr && _fio.usage_count[i] < count) {
232 count = _fio.usage_count[i];
237 DEBUG(misc, 6,
"Closing filehandler '%s' in slot '%d' because of fd-limit", _fio.
filenames[slot], slot);
253 #if defined(LIMITED_FDS) 257 if (f ==
nullptr)
usererror(
"Cannot open file '%s'", filename);
259 if (pos < 0)
usererror(
"Cannot read file '%s'", filename);
266 const char *t = strrchr(filename, PATHSEPCHAR);
268 char *t2 = strrchr(_fio.
shortnames[slot],
'.');
269 if (t2 !=
nullptr) *t2 =
'\0';
272 #if defined(LIMITED_FDS) 273 _fio.usage_count[slot] = 0;
279 static const char *
const _subdirs[] = {
282 "save" PATHSEP
"autosave" PATHSEP,
284 "scenario" PATHSEP
"heightmap" PATHSEP,
291 "ai" PATHSEP
"library" PATHSEP,
293 "game" PATHSEP
"library" PATHSEP,
294 "screenshot" PATHSEP,
302 typedef std::map<std::string, std::string> TarLinkList;
314 if (f ==
nullptr)
return false;
327 return access(
OTTD2FS(filename), 0) == 0;
341 assert(sp < NUM_SEARCHPATHS);
361 FioGetFullPath(buf, last, sp, subdir, filename);
377 assert(sp < NUM_SEARCHPATHS);
383 char *FioGetDirectory(
char *buf,
const char *last,
Subdirectory subdir)
389 char *ret = FioAppendDirectory(buf, last, sp, subdir);
401 #if defined(_WIN32) && defined(UNICODE) 407 MultiByteToWideChar(CP_ACP, 0, mode, -1, Lmode,
lengthof(Lmode));
419 if (mode[0] ==
'r' && GetFileAttributes(
OTTD2FS(buf)) == INVALID_FILE_ATTRIBUTES)
return nullptr;
422 f = fopen(buf, mode);
425 f = fopen(buf, mode);
428 if (f !=
nullptr && filesize !=
nullptr) {
430 fseek(f, 0, SEEK_END);
431 *filesize = ftell(f);
432 fseek(f, 0, SEEK_SET);
446 FILE *f = fopen(entry->tar_filename,
"rb");
447 if (f ==
nullptr)
return f;
449 if (fseek(f, entry->position, SEEK_SET) < 0) {
454 if (filesize !=
nullptr) *filesize = entry->size;
472 f = FioFOpenFileSp(filename, mode, sp, subdir, filesize);
477 if (f ==
nullptr && mode[0] ==
'r' && subdir !=
NO_DIRECTORY) {
478 static const uint MAX_RESOLVED_LENGTH = 2 * (100 + 100 + 155) + 1;
479 char resolved_name[MAX_RESOLVED_LENGTH];
486 std::istringstream ss(resolved_name);
487 std::vector<std::string> tokens;
489 while (std::getline(ss, token, PATHSEPCHAR)) {
491 if (tokens.size() < 2)
return nullptr;
494 tokens.push_back(token);
497 resolved_name[0] =
'\0';
499 for (
const std::string &token : tokens) {
503 strecat(resolved_name, token.c_str(),
lastof(resolved_name));
507 size_t resolved_len = strlen(resolved_name);
511 const std::string &src = link->first;
512 size_t len = src.length();
513 if (resolved_len >= len && resolved_name[len - 1] == PATHSEPCHAR && strncmp(src.c_str(), resolved_name, len) == 0) {
515 char resolved_name2[MAX_RESOLVED_LENGTH];
516 const std::string &dest = link->second;
517 strecpy(resolved_name2, &(resolved_name[len]),
lastof(resolved_name2));
519 strecpy(&(resolved_name[dest.length()]), resolved_name2,
lastof(resolved_name));
524 TarFileList::iterator it = _tar_filelist[subdir].find(resolved_name);
525 if (it != _tar_filelist[subdir].end()) {
536 if (f !=
nullptr)
break;
558 char dirname[MAX_PATH];
560 char *p = strrchr(dirname, PATHSEPCHAR);
564 if (dir ==
nullptr) {
574 CreateDirectory(
OTTD2FS(name),
nullptr);
575 #elif defined(OS2) && !defined(__INNOTEK_LIBC__) 591 size_t s = strlen(buf);
594 if (s != 0 && buf[s - 1] != PATHSEPCHAR) {
595 if (&buf[s] >= last)
return false;
597 seprintf(buf + s, last,
"%c", PATHSEPCHAR);
603 static void TarAddLink(
const std::string &srcParam,
const std::string &destParam,
Subdirectory subdir)
605 std::string src = srcParam;
606 std::string dest = destParam;
608 std::transform(src.begin(), src.end(), src.begin(), tolower);
609 std::transform(dest.begin(), dest.end(), dest.begin(), tolower);
611 TarFileList::iterator dest_file = _tar_filelist[subdir].find(dest);
612 if (dest_file != _tar_filelist[subdir].end()) {
614 _tar_filelist[subdir].insert(TarFileList::value_type(src, dest_file->second));
618 const std::string src_path = ((*src.rbegin() == PATHSEPCHAR) ? src : src + PATHSEPCHAR);
619 const std::string dst_path = (dest.length() == 0 ?
"" : ((*dest.rbegin() == PATHSEPCHAR) ? dest : dest + PATHSEPCHAR));
620 _tar_linklist[subdir].insert(TarLinkList::value_type(src_path, dst_path));
635 #if (PATHSEPCHAR != '/') 636 for (
char *n = name; *n !=
'\0'; n++)
if (*n ==
'/') *n = PATHSEPCHAR;
647 _tar_filelist[sd].clear();
648 _tar_list[sd].clear();
649 uint num = this->Scan(
".tar", sd,
false);
656 DEBUG(misc, 1,
"Scanning for tars");
677 DEBUG(misc, 1,
"Scan complete, found %d files", num);
690 return this->AddFile(filename, 0);
696 assert(tar_filename ==
nullptr);
721 TarList::iterator it = _tar_list[this->subdir].find(filename);
722 if (it != _tar_list[this->subdir].end())
return false;
724 FILE *f = fopen(filename,
"rb");
729 if (f ==
nullptr)
return false;
731 const char *dupped_filename =
stredup(filename);
732 _tar_list[this->subdir][
filename].filename = dupped_filename;
733 _tar_list[this->subdir][
filename].dirname =
nullptr;
738 char buf[
sizeof(th.name) + 1], *end;
739 char name[
sizeof(th.prefix) + 1 +
sizeof(th.name) + 1];
740 char link[
sizeof(th.linkname) + 1];
741 char dest[
sizeof(th.prefix) + 1 +
sizeof(th.name) + 1 + 1 +
sizeof(th.linkname) + 1];
742 size_t num = 0,
pos = 0;
746 memset(&empty[0], 0,
sizeof(empty));
749 size_t num_bytes_read = fread(&th, 1, 512, f);
750 if (num_bytes_read != 512)
break;
751 pos += num_bytes_read;
754 if (strncmp(th.magic,
"ustar", 5) != 0 && memcmp(&th.magic, &empty[0], 512 - offsetof(TarHeader, magic)) != 0) {
756 if (memcmp(&th, &empty[0], 512) == 0)
continue;
758 DEBUG(misc, 0,
"The file '%s' isn't a valid tar-file", filename);
766 if (th.prefix[0] !=
'\0') {
776 size_t skip = strtoul(buf, &end, 8);
778 switch (th.typeflag) {
782 if (skip == 0)
break;
784 if (strlen(name) == 0)
break;
788 entry.tar_filename = dupped_filename;
790 entry.position =
pos;
795 DEBUG(misc, 6,
"Found file in tar: %s (" PRINTF_SIZE
" bytes, " PRINTF_SIZE
" offset)", name, skip,
pos);
796 if (_tar_filelist[this->subdir].insert(TarFileList::value_type(name, entry)).second) num++;
806 if (strlen(name) == 0 || strlen(link) == 0)
break;
813 if (link[0] == PATHSEPCHAR) {
814 DEBUG(misc, 1,
"Ignoring absolute link in tar: %s -> %s", name, link);
821 char *destpos = strrchr(dest, PATHSEPCHAR);
822 if (destpos ==
nullptr) destpos = dest;
826 while (*pos !=
'\0') {
827 char *next = strchr(pos, PATHSEPCHAR);
828 if (next ==
nullptr) {
829 next = pos + strlen(pos);
835 if (strcmp(pos,
".") == 0) {
837 }
else if (strcmp(pos,
"..") == 0) {
839 if (dest[0] ==
'\0') {
840 DEBUG(misc, 1,
"Ignoring link pointing outside of data directory: %s -> %s", name, link);
846 destpos = strrchr(dest, PATHSEPCHAR);
847 if (destpos ==
nullptr) destpos = dest;
851 if (destpos != dest) destpos =
strecpy(destpos, PATHSEP,
lastof(dest));
855 if (destpos >=
lastof(dest)) {
856 DEBUG(misc, 0,
"The length of a link in tar-file '%s' is too large (malformed?)", filename);
865 DEBUG(misc, 6,
"Found link in tar: %s -> %s", name, dest);
866 links.insert(TarLinkList::value_type(name, dest));
876 DEBUG(misc, 6,
"Found dir in tar: %s", name);
877 if (_tar_list[this->subdir][filename].dirname ==
nullptr) _tar_list[this->subdir][
filename].dirname =
stredup(name);
886 skip =
Align(skip, 512);
887 if (fseek(f, skip, SEEK_CUR) < 0) {
888 DEBUG(misc, 0,
"The file '%s' can't be read as a valid tar-file", filename);
895 DEBUG(misc, 1,
"Found tar '%s' with " PRINTF_SIZE
" new files", filename, num);
907 for (TarLinkList::iterator link = links.begin(); link != links.end(); link++) {
908 const std::string &src = link->first;
909 const std::string &dest = link->second;
910 TarAddLink(src, dest, this->subdir);
925 TarList::iterator it = _tar_list[subdir].find(tar_filename);
927 if (it == _tar_list[subdir].end())
return false;
929 const char *dirname = (*it).second.dirname;
932 if (dirname ==
nullptr) {
933 DEBUG(misc, 1,
"Extracting %s failed; archive rejected, the contents must be in a sub directory", tar_filename);
939 char *p = strrchr(filename, PATHSEPCHAR);
941 if (p ==
nullptr)
return false;
945 DEBUG(misc, 8,
"Extracting %s to directory %s", tar_filename, filename);
948 for (TarFileList::iterator it2 = _tar_filelist[subdir].begin(); it2 != _tar_filelist[subdir].end(); it2++) {
949 if (strcmp((*it2).second.tar_filename, tar_filename) != 0)
continue;
953 DEBUG(misc, 9,
" extracting %s", filename);
959 DEBUG(misc, 6,
"Extracting %s failed; could not open %s", filename, tar_filename);
964 FILE *out = fopen(filename,
"wb");
965 if (out ==
nullptr) {
966 DEBUG(misc, 6,
"Extracting %s failed; could not open %s", filename, filename);
974 for (; to_copy != 0; to_copy -= read) {
975 read = fread(buffer, 1,
min(to_copy,
lengthof(buffer)), in);
976 if (read <= 0 || fwrite(buffer, 1, read, out) != read)
break;
984 DEBUG(misc, 6,
"Extracting %s failed; still %i bytes to copy", filename, (
int)to_copy);
989 DEBUG(misc, 9,
" extraction successful");
1014 bool success =
false;
1016 char *app_bundle = strchr(tmp,
'.');
1017 while (app_bundle !=
nullptr && strncasecmp(app_bundle,
".app", 4) != 0) app_bundle = strchr(&app_bundle[1],
'.');
1019 if (app_bundle !=
nullptr) *app_bundle =
'\0';
1021 char *s = strrchr(tmp, PATHSEPCHAR);
1024 if (chdir(tmp) != 0) {
1025 DEBUG(misc, 0,
"Directory with the binary does not exist?");
1067 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1068 const char *xdg_data_home = xdgDataHome(
nullptr);
1070 PERSONAL_DIR[0] ==
'.' ? &PERSONAL_DIR[1] : PERSONAL_DIR);
1071 free(xdg_data_home);
1076 #if defined(OS2) || !defined(WITH_PERSONAL_DIR) 1081 find_directory(B_USER_SETTINGS_DIRECTORY, &path);
1082 const char *homedir =
stredup(path.Path());
1088 const char *homedir = getenv(
"HOME");
1089 if (homedir !=
nullptr) {
1093 if (homedir ==
nullptr) {
1094 const struct passwd *pw = getpwuid(getuid());
1095 homedir = (pw ==
nullptr) ?
nullptr :
stredup(pw->pw_dir);
1099 if (homedir !=
nullptr) {
1101 seprintf(tmp,
lastof(tmp),
"%s" PATHSEP
"%s", homedir, PERSONAL_DIR);
1111 #if defined(WITH_SHARED_DIR) 1119 if (getcwd(tmp, MAX_PATH) ==
nullptr) *tmp =
'\0';
1127 if (getcwd(tmp, MAX_PATH) ==
nullptr) *tmp =
'\0';
1137 DEBUG(misc, 0,
"Failed to return to working directory!");
1141 #if !defined(GLOBAL_DATA_DIR) 1149 extern void cocoaSetApplicationBundleDir();
1150 cocoaSetApplicationBundleDir();
1169 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1170 char config_home[MAX_PATH];
1172 const char *xdg_config_home = xdgConfigHome(
nullptr);
1173 seprintf(config_home,
lastof(config_home),
"%s" PATHSEP
"%s", xdg_config_home,
1174 PERSONAL_DIR[0] ==
'.' ? &PERSONAL_DIR[1] : PERSONAL_DIR);
1175 free(xdg_config_home);
1189 char *end = strrchr(config_dir, PATHSEPCHAR);
1190 if (end ==
nullptr) {
1191 config_dir[0] =
'\0';
1196 char personal_dir[MAX_PATH];
1198 char *end = strrchr(personal_dir, PATHSEPCHAR);
1199 if (end !=
nullptr) end[1] =
'\0';
1200 config_dir =
stredup(personal_dir);
1203 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1205 config_dir = config_home;
1207 static const Searchpath new_openttd_cfg_order[] = {
1211 config_dir =
nullptr;
1212 for (uint i = 0; i <
lengthof(new_openttd_cfg_order); i++) {
1218 assert(config_dir !=
nullptr);
1224 DEBUG(misc, 3,
"%s found as config directory", config_dir);
1227 extern char *_hotkeys_file;
1228 _hotkeys_file =
str_fmt(
"%shotkeys.cfg", config_dir);
1230 _windows_file =
str_fmt(
"%swindows.cfg", config_dir);
1232 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1233 if (config_dir == config_home) {
1245 #if defined(WITH_PERSONAL_DIR) 1253 SAVE_DIR,
AUTOSAVE_DIR,
SCENARIO_DIR,
HEIGHTMAP_DIR,
BASESET_DIR,
NEWGRF_DIR,
AI_DIR,
AI_LIBRARY_DIR,
GAME_DIR,
GAME_LIBRARY_DIR,
SCREENSHOT_DIR 1256 for (uint i = 0; i <
lengthof(default_subdirs); i++) {
1268 for (uint i = 0; i <
lengthof(dirs); i++) {
1284 for (; *filename !=
'\0'; filename++) {
1285 switch (*filename) {
1288 case ':':
case '\\':
case '*':
case '?':
case '/':
1289 case '<':
case '>':
case '|':
case '"':
1306 FILE *in = fopen(filename,
"rb");
1307 if (in ==
nullptr)
return nullptr;
1309 fseek(in, 0, SEEK_END);
1310 size_t len = ftell(in);
1311 fseek(in, 0, SEEK_SET);
1312 if (len > maxsize) {
1316 byte *mem = MallocT<byte>(len + 1);
1318 if (fread(mem, len, 1, in) != 1) {
1337 if (extension ==
nullptr)
return true;
1339 const char *ext = strrchr(filename, extension[0]);
1340 return ext !=
nullptr && strcasecmp(ext, extension) == 0;
1352 static uint
ScanPath(
FileScanner *fs,
const char *extension,
const char *path,
size_t basepath_length,
bool recursive)
1354 extern bool FiosIsValidFile(
const char *path,
const struct dirent *ent,
struct stat *sb);
1358 struct dirent *dirent;
1361 if (path ==
nullptr || (dir =
ttd_opendir(path)) ==
nullptr)
return 0;
1363 while ((dirent = readdir(dir)) !=
nullptr) {
1364 const char *d_name =
FS2OTTD(dirent->d_name);
1367 if (!FiosIsValidFile(path, dirent, &sb))
continue;
1371 if (S_ISDIR(sb.st_mode)) {
1373 if (!recursive)
continue;
1374 if (strcmp(d_name,
".") == 0 || strcmp(d_name,
"..") == 0)
continue;
1376 num +=
ScanPath(fs, extension, filename, basepath_length, recursive);
1377 }
else if (S_ISREG(sb.st_mode)) {
1397 const char *
filename = (*tar).first.c_str();
1418 char path[MAX_PATH];
1419 TarFileList::iterator tar;
1426 FioAppendDirectory(path,
lastof(path), sp, sd);
1427 num +=
ScanPath(
this, extension, path, strlen(path), recursive);
1431 FOR_ALL_TARS(tar, sd) {
1432 num +=
ScanTar(
this, extension, tar);
1438 num += this->Scan(extension,
OLD_GM_DIR, tars, recursive);
1441 num += this->Scan(extension,
OLD_DATA_DIR, tars, recursive);
1460 char path[MAX_PATH];
1463 return ScanPath(
this, extension, path, strlen(path), recursive);
bool DoScanWorkingDirectory()
Whether we should scan the working directory.
FILE * handles[MAX_FILE_SLOTS]
array of file handles we can have open
Old subdirectory for the music.
char *CDECL str_fmt(const char *str,...)
Format, "printf", into a newly allocated string.
FILE * cur_fh
current file handle
static bool _do_scan_working_directory
Whether the working directory should be scanned.
static char * strecat(char *dst, const char *src, const char *last)
Appends characters from one string to another.
const char * FS2OTTD(const TCHAR *name)
Convert to OpenTTD's encoding from that of the local environment.
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Number of subdirectories.
void FioFCloseFile(FILE *f)
Close a file in a safe way.
Structs, typedefs and macros used for TAR file handling.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Search in the directory where the binary resides.
Functions related to debugging.
uint Scan(const char *extension, Subdirectory sd, bool tars=true, bool recursive=true)
Scan for files with the given extension in the given search path.
uint16 FioReadWord()
Read a word (16 bits) from the file (in low endian format).
#define FOR_ALL_SEARCHPATHS(sp)
Iterator for all the search paths.
Subdirectory of scenario for heightmaps.
Subdirectory for all screenshots.
#define FIO_BUFFER_SIZE
Size of the Fio data buffer.
void FioCloseAll()
Close all slotted open files.
byte buffer_start[FIO_BUFFER_SIZE]
local buffer when read from file
Subdirectory for all game scripts.
Functions for Standard In/Out file operations.
Helper for scanning for files with tar as extension.
static uint ScanTar(FileScanner *fs, const char *extension, TarFileList::iterator tar)
Scan the given tar and add graphics sets when it finds one.
const char * FioGetFilename(uint8 slot)
Get the filename associated with a slot.
#define lastof(x)
Get the last element of an fixed size array.
bool strtolower(char *str)
Convert a given ASCII string to lowercase.
Searchpath
Types of searchpaths OpenTTD might use.
Subdirectory for all base data (base sets, intro game)
byte FioReadByte()
Read a byte from the file.
const char * filename
current filename
virtual bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename)=0
Add a file with the given filename.
Helper for scanning for files with a given name.
char * _log_file
File to reroute output of a forked OpenTTD to.
Functions related to low-level strings.
Base directory for all scenarios.
byte * buffer_end
position pointer in local buffer and last valid byte of buffer
bool AppendPathSeparator(char *buf, const char *last)
Appends, if necessary, the path separator character to the end of the string.
static T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
char * _config_file
Configuration file of OpenTTD.
char * FioFindFullPath(char *buf, const char *last, Subdirectory subdir, const char *filename)
Find a path to the filename in one of the search directories.
static TarLinkList _tar_linklist[NUM_SUBDIRS]
List of directory links.
FILE * FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir, size_t *filesize)
Opens a OpenTTD file somewhere in a personal or global directory.
A path without any base directory.
bool FileExists(const char *filename)
Test whether the given filename exists.
Definition of base types and functions in a cross-platform compatible way.
static bool ChangeWorkingDirectoryToExecutable(const char *exe)
Changes the working directory to the path of the give executable.
void CDECL usererror(const char *s,...)
Error handling for fatal user errors.
A number of safeguards to prevent using unsafe methods.
void FioSeekTo(size_t pos, int mode)
Seek in the current file.
static void SimplifyFileName(char *name)
Simplify filenames from tars.
Scan for scenarios and heightmaps.
Base directory for all savegames.
Subdirectory of save for autosaves.
void SanitizeFilename(char *filename)
Sanitizes a filename, i.e.
Base directory for all subdirectories.
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
const char * _personal_dir
custom directory for personal settings, saves, newgrf, etc.
void FioSeekToFile(uint8 slot, size_t pos)
Switch to a different file and seek to a position.
Subdirectory for all GS libraries.
Search within the autodownload directory.
void FioReadBlock(void *ptr, size_t size)
Read a block.
#define lengthof(x)
Return the length of an fixed size array.
static T min(const T a, const T b)
Returns the minimum of two values.
bool FioCheckFileExists(const char *filename, Subdirectory subdir)
Check whether the given file exists.
void DetermineBasePaths(const char *exe)
Determine the base (personal dir and game data dir) paths.
const TCHAR * OTTD2FS(const char *name, bool console_cp)
Convert from OpenTTD's encoding to that of the local environment.
Subdirectory for all NewGRFs.
Structure for keeping several open files with just one data buffer.
static uint ScanPath(FileScanner *fs, const char *extension, const char *path, size_t basepath_length, bool recursive)
Scan a single directory (and recursively its children) and add any graphics sets that are found...
uint DoScan(Subdirectory sd)
Perform the scanning of a particular subdirectory.
const char * filenames[MAX_FILE_SLOTS]
array of filenames we (should) have open
#define DEBUG(name, level,...)
Output a line of debugging information.
bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename=nullptr) override
Add a file with the given filename.
void FioOpenFile(int slot, const char *filename, Subdirectory subdir)
Open a slotted file.
Subdirectory for all AI libraries.
uint32 FioReadDword()
Read a double word (32 bits) from the file (in low endian format).
Mode
The mode of tar scanning.
Search in the personal directory.
char * shortnames[MAX_FILE_SLOTS]
array of short names for spriteloader's use
void DeterminePaths(const char *exe)
Acquire the base paths (personal dir and game data dir), fill all other paths (save dir...
char * _highscore_file
The file to store the highscore data in.
Declarations for savegames operations.
static bool MatchesExtension(const char *extension, const char *filename)
Helper to see whether a given filename matches the extension.
const char * _searchpaths[NUM_SEARCHPATHS]
The search paths OpenTTD could search through.
void FioSkipBytes(int n)
Skip n bytes ahead in the file.
Subdirectory for all AI files.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
static DIR * ttd_opendir(const char *path)
A wrapper around opendir() which will convert the string from OPENTTD encoding to that of the filesys...
Search in the working directory.
FILE * FioFOpenFileTar(TarFileListEntry *entry, size_t *filesize)
Opens a file from inside a tar archive.
Scan for AIs and its libraries.
Search in the installation directory.
bool ExtractTar(const char *tar_filename, Subdirectory subdir)
Extract the tar with the given filename in the directory where the tar resides.
Search within the application bundle.
static Fio _fio
Fio instance.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
size_t pos
current (system) position in file
void * ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize)
Load a file into memory.
void ValidateString(const char *str)
Scans the string for valid characters and if it finds invalid ones, replaces them with a question mar...
static bool IsValidSearchPath(Searchpath sp)
Checks whether the given search path is a valid search path.
size_t FioGetPos()
Get position in the current file.
void FioCreateDirectory(const char *name)
Create a directory with the given name If the parent directory does not exist, it will try to create ...
static void FioCloseFile(int slot)
Close the file at the given slot number.
Search in the shared directory, like 'Shared Files' under Windows.
char * _windows_file
Config file to store WindowDesc.
Old subdirectory for the data.