18 # define access _taccess 19 #elif defined(__HAIKU__) 21 #include <storage/FindDirectory.h> 29 #ifdef WITH_XDG_BASEDIR 36 #define FIO_BUFFER_SIZE 512 48 #if defined(LIMITED_FDS) 91 if (fseek(_fio.
cur_fh, _fio.
pos, SEEK_SET) < 0) {
96 #if defined(LIMITED_FDS) 97 static void FioRestoreFile(
int slot)
100 if (_fio.
handles[slot] ==
nullptr) {
101 DEBUG(misc, 6,
"Restoring file '%s' in slot '%d' from disk", _fio.
filenames[slot], slot);
104 _fio.usage_count[slot]++;
116 #if defined(LIMITED_FDS) 118 FioRestoreFile(slot);
121 assert(f !=
nullptr);
139 if (size == 0)
return 0;
141 return *_fio.buffer++;
188 _fio.
pos += fread(ptr, 1, size, _fio.
cur_fh);
197 if (_fio.
handles[slot] !=
nullptr) {
204 #if defined(LIMITED_FDS) 218 #if defined(LIMITED_FDS) 219 static void FioFreeHandle()
222 if (_fio.open_handles + 1 == LIMITED_FDS) {
230 if (_fio.
handles[i] !=
nullptr && _fio.usage_count[i] < count) {
231 count = _fio.usage_count[i];
236 DEBUG(misc, 6,
"Closing filehandler '%s' in slot '%d' because of fd-limit", _fio.
filenames[slot], slot);
252 #if defined(LIMITED_FDS) 256 if (f ==
nullptr)
usererror(
"Cannot open file '%s'", filename);
258 if (pos < 0)
usererror(
"Cannot read file '%s'", filename);
265 const char *t = strrchr(filename, PATHSEPCHAR);
267 char *t2 = strrchr(_fio.
shortnames[slot],
'.');
268 if (t2 !=
nullptr) *t2 =
'\0';
271 #if defined(LIMITED_FDS) 272 _fio.usage_count[slot] = 0;
278 static const char *
const _subdirs[] = {
281 "save" PATHSEP
"autosave" PATHSEP,
283 "scenario" PATHSEP
"heightmap" PATHSEP,
290 "ai" PATHSEP
"library" PATHSEP,
292 "game" PATHSEP
"library" PATHSEP,
293 "screenshot" PATHSEP,
301 typedef std::map<std::string, std::string> TarLinkList;
313 if (f ==
nullptr)
return false;
326 return access(
OTTD2FS(filename), 0) == 0;
340 assert(sp < NUM_SEARCHPATHS);
360 FioGetFullPath(buf, last, sp, subdir, filename);
376 assert(sp < NUM_SEARCHPATHS);
382 char *FioGetDirectory(
char *buf,
const char *last,
Subdirectory subdir)
388 char *ret = FioAppendDirectory(buf, last, sp, subdir);
400 #if defined(_WIN32) && defined(UNICODE) 406 MultiByteToWideChar(CP_ACP, 0, mode, -1, Lmode,
lengthof(Lmode));
418 if (mode[0] ==
'r' && GetFileAttributes(
OTTD2FS(buf)) == INVALID_FILE_ATTRIBUTES)
return nullptr;
421 f = fopen(buf, mode);
424 f = fopen(buf, mode);
427 if (f !=
nullptr && filesize !=
nullptr) {
429 fseek(f, 0, SEEK_END);
430 *filesize = ftell(f);
431 fseek(f, 0, SEEK_SET);
445 FILE *f = fopen(entry->tar_filename,
"rb");
446 if (f ==
nullptr)
return f;
448 if (fseek(f, entry->position, SEEK_SET) < 0) {
453 if (filesize !=
nullptr) *filesize = entry->size;
471 f = FioFOpenFileSp(filename, mode, sp, subdir, filesize);
476 if (f ==
nullptr && mode[0] ==
'r' && subdir !=
NO_DIRECTORY) {
477 static const uint MAX_RESOLVED_LENGTH = 2 * (100 + 100 + 155) + 1;
478 char resolved_name[MAX_RESOLVED_LENGTH];
484 size_t resolved_len = strlen(resolved_name);
488 const std::string &src = link->first;
489 size_t len = src.length();
490 if (resolved_len >= len && resolved_name[len - 1] == PATHSEPCHAR && strncmp(src.c_str(), resolved_name, len) == 0) {
492 char resolved_name2[MAX_RESOLVED_LENGTH];
493 const std::string &dest = link->second;
494 strecpy(resolved_name2, &(resolved_name[len]),
lastof(resolved_name2));
496 strecpy(&(resolved_name[dest.length()]), resolved_name2,
lastof(resolved_name));
501 TarFileList::iterator it = _tar_filelist[subdir].find(resolved_name);
502 if (it != _tar_filelist[subdir].end()) {
513 if (f !=
nullptr)
break;
535 char dirname[MAX_PATH];
537 char *p = strrchr(dirname, PATHSEPCHAR);
541 if (dir ==
nullptr) {
551 CreateDirectory(
OTTD2FS(name),
nullptr);
552 #elif defined(OS2) && !defined(__INNOTEK_LIBC__) 568 size_t s = strlen(buf);
571 if (s != 0 && buf[s - 1] != PATHSEPCHAR) {
572 if (&buf[s] >= last)
return false;
574 seprintf(buf + s, last,
"%c", PATHSEPCHAR);
580 static void TarAddLink(
const std::string &srcParam,
const std::string &destParam,
Subdirectory subdir)
582 std::string src = srcParam;
583 std::string dest = destParam;
585 std::transform(src.begin(), src.end(), src.begin(), tolower);
586 std::transform(dest.begin(), dest.end(), dest.begin(), tolower);
588 TarFileList::iterator dest_file = _tar_filelist[subdir].find(dest);
589 if (dest_file != _tar_filelist[subdir].end()) {
591 _tar_filelist[subdir].insert(TarFileList::value_type(src, dest_file->second));
595 const std::string src_path = ((*src.rbegin() == PATHSEPCHAR) ? src : src + PATHSEPCHAR);
596 const std::string dst_path = (dest.length() == 0 ?
"" : ((*dest.rbegin() == PATHSEPCHAR) ? dest : dest + PATHSEPCHAR));
597 _tar_linklist[subdir].insert(TarLinkList::value_type(src_path, dst_path));
612 #if (PATHSEPCHAR != '/') 613 for (
char *n = name; *n !=
'\0'; n++)
if (*n ==
'/') *n = PATHSEPCHAR;
624 _tar_filelist[sd].clear();
625 _tar_list[sd].clear();
626 uint num = this->Scan(
".tar", sd,
false);
633 DEBUG(misc, 1,
"Scanning for tars");
654 DEBUG(misc, 1,
"Scan complete, found %d files", num);
667 return this->AddFile(filename, 0);
673 assert(tar_filename ==
nullptr);
698 TarList::iterator it = _tar_list[this->subdir].find(filename);
699 if (it != _tar_list[this->subdir].end())
return false;
701 FILE *f = fopen(filename,
"rb");
706 if (f ==
nullptr)
return false;
708 const char *dupped_filename =
stredup(filename);
709 _tar_list[this->subdir][
filename].filename = dupped_filename;
710 _tar_list[this->subdir][
filename].dirname =
nullptr;
715 char buf[
sizeof(th.name) + 1], *end;
716 char name[
sizeof(th.prefix) + 1 +
sizeof(th.name) + 1];
717 char link[
sizeof(th.linkname) + 1];
718 char dest[
sizeof(th.prefix) + 1 +
sizeof(th.name) + 1 + 1 +
sizeof(th.linkname) + 1];
719 size_t num = 0,
pos = 0;
723 memset(&empty[0], 0,
sizeof(empty));
726 size_t num_bytes_read = fread(&th, 1, 512, f);
727 if (num_bytes_read != 512)
break;
728 pos += num_bytes_read;
731 if (strncmp(th.magic,
"ustar", 5) != 0 && memcmp(&th.magic, &empty[0], 512 - offsetof(TarHeader, magic)) != 0) {
733 if (memcmp(&th, &empty[0], 512) == 0)
continue;
735 DEBUG(misc, 0,
"The file '%s' isn't a valid tar-file", filename);
743 if (th.prefix[0] !=
'\0') {
753 size_t skip = strtoul(buf, &end, 8);
755 switch (th.typeflag) {
759 if (skip == 0)
break;
761 if (strlen(name) == 0)
break;
765 entry.tar_filename = dupped_filename;
767 entry.position =
pos;
772 DEBUG(misc, 6,
"Found file in tar: %s (" PRINTF_SIZE
" bytes, " PRINTF_SIZE
" offset)", name, skip,
pos);
773 if (_tar_filelist[this->subdir].insert(TarFileList::value_type(name, entry)).second) num++;
783 if (strlen(name) == 0 || strlen(link) == 0)
break;
790 if (link[0] == PATHSEPCHAR) {
791 DEBUG(misc, 1,
"Ignoring absolute link in tar: %s -> %s", name, link);
798 char *destpos = strrchr(dest, PATHSEPCHAR);
799 if (destpos ==
nullptr) destpos = dest;
803 while (*pos !=
'\0') {
804 char *next = strchr(pos, PATHSEPCHAR);
805 if (next ==
nullptr) {
806 next = pos + strlen(pos);
812 if (strcmp(pos,
".") == 0) {
814 }
else if (strcmp(pos,
"..") == 0) {
816 if (dest[0] ==
'\0') {
817 DEBUG(misc, 1,
"Ignoring link pointing outside of data directory: %s -> %s", name, link);
823 destpos = strrchr(dest, PATHSEPCHAR);
824 if (destpos ==
nullptr) destpos = dest;
828 if (destpos != dest) destpos =
strecpy(destpos, PATHSEP,
lastof(dest));
832 if (destpos >=
lastof(dest)) {
833 DEBUG(misc, 0,
"The length of a link in tar-file '%s' is too large (malformed?)", filename);
842 DEBUG(misc, 6,
"Found link in tar: %s -> %s", name, dest);
843 links.insert(TarLinkList::value_type(name, dest));
853 DEBUG(misc, 6,
"Found dir in tar: %s", name);
854 if (_tar_list[this->subdir][filename].dirname ==
nullptr) _tar_list[this->subdir][
filename].dirname =
stredup(name);
863 skip =
Align(skip, 512);
864 if (fseek(f, skip, SEEK_CUR) < 0) {
865 DEBUG(misc, 0,
"The file '%s' can't be read as a valid tar-file", filename);
872 DEBUG(misc, 1,
"Found tar '%s' with " PRINTF_SIZE
" new files", filename, num);
884 for (TarLinkList::iterator link = links.begin(); link != links.end(); link++) {
885 const std::string &src = link->first;
886 const std::string &dest = link->second;
887 TarAddLink(src, dest, this->subdir);
902 TarList::iterator it = _tar_list[subdir].find(tar_filename);
904 if (it == _tar_list[subdir].end())
return false;
906 const char *dirname = (*it).second.dirname;
909 if (dirname ==
nullptr)
return false;
913 char *p = strrchr(filename, PATHSEPCHAR);
915 if (p ==
nullptr)
return false;
919 DEBUG(misc, 8,
"Extracting %s to directory %s", tar_filename, filename);
922 for (TarFileList::iterator it2 = _tar_filelist[subdir].begin(); it2 != _tar_filelist[subdir].end(); it2++) {
923 if (strcmp((*it2).second.tar_filename, tar_filename) != 0)
continue;
927 DEBUG(misc, 9,
" extracting %s", filename);
933 DEBUG(misc, 6,
"Extracting %s failed; could not open %s", filename, tar_filename);
938 FILE *out = fopen(filename,
"wb");
939 if (out ==
nullptr) {
940 DEBUG(misc, 6,
"Extracting %s failed; could not open %s", filename, filename);
948 for (; to_copy != 0; to_copy -= read) {
949 read = fread(buffer, 1,
min(to_copy,
lengthof(buffer)), in);
950 if (read <= 0 || fwrite(buffer, 1, read, out) != read)
break;
958 DEBUG(misc, 6,
"Extracting %s failed; still %i bytes to copy", filename, (
int)to_copy);
963 DEBUG(misc, 9,
" extraction successful");
988 bool success =
false;
990 char *app_bundle = strchr(tmp,
'.');
991 while (app_bundle !=
nullptr && strncasecmp(app_bundle,
".app", 4) != 0) app_bundle = strchr(&app_bundle[1],
'.');
993 if (app_bundle !=
nullptr) *app_bundle =
'\0';
995 char *s = strrchr(tmp, PATHSEPCHAR);
998 if (chdir(tmp) != 0) {
999 DEBUG(misc, 0,
"Directory with the binary does not exist?");
1041 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1042 const char *xdg_data_home = xdgDataHome(
nullptr);
1044 PERSONAL_DIR[0] ==
'.' ? &PERSONAL_DIR[1] : PERSONAL_DIR);
1045 free(xdg_data_home);
1050 #if defined(OS2) || !defined(WITH_PERSONAL_DIR) 1055 find_directory(B_USER_SETTINGS_DIRECTORY, &path);
1056 const char *homedir =
stredup(path.Path());
1062 const char *homedir = getenv(
"HOME");
1063 if (homedir !=
nullptr) {
1067 if (homedir ==
nullptr) {
1068 const struct passwd *pw = getpwuid(getuid());
1069 homedir = (pw ==
nullptr) ?
nullptr :
stredup(pw->pw_dir);
1073 if (homedir !=
nullptr) {
1075 seprintf(tmp,
lastof(tmp),
"%s" PATHSEP
"%s", homedir, PERSONAL_DIR);
1085 #if defined(WITH_SHARED_DIR) 1093 if (getcwd(tmp, MAX_PATH) ==
nullptr) *tmp =
'\0';
1101 if (getcwd(tmp, MAX_PATH) ==
nullptr) *tmp =
'\0';
1111 DEBUG(misc, 0,
"Failed to return to working directory!");
1115 #if !defined(GLOBAL_DATA_DIR) 1123 extern void cocoaSetApplicationBundleDir();
1124 cocoaSetApplicationBundleDir();
1143 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1144 char config_home[MAX_PATH];
1146 const char *xdg_config_home = xdgConfigHome(
nullptr);
1147 seprintf(config_home,
lastof(config_home),
"%s" PATHSEP
"%s", xdg_config_home,
1148 PERSONAL_DIR[0] ==
'.' ? &PERSONAL_DIR[1] : PERSONAL_DIR);
1149 free(xdg_config_home);
1163 char *end = strrchr(config_dir, PATHSEPCHAR);
1164 if (end ==
nullptr) {
1165 config_dir[0] =
'\0';
1170 char personal_dir[MAX_PATH];
1172 char *end = strrchr(personal_dir, PATHSEPCHAR);
1173 if (end !=
nullptr) end[1] =
'\0';
1174 config_dir =
stredup(personal_dir);
1177 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1179 config_dir = config_home;
1181 static const Searchpath new_openttd_cfg_order[] = {
1185 config_dir =
nullptr;
1186 for (uint i = 0; i <
lengthof(new_openttd_cfg_order); i++) {
1192 assert(config_dir !=
nullptr);
1198 DEBUG(misc, 3,
"%s found as config directory", config_dir);
1201 extern char *_hotkeys_file;
1202 _hotkeys_file =
str_fmt(
"%shotkeys.cfg", config_dir);
1204 _windows_file =
str_fmt(
"%swindows.cfg", config_dir);
1206 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1207 if (config_dir == config_home) {
1219 #if defined(WITH_PERSONAL_DIR) 1227 SAVE_DIR,
AUTOSAVE_DIR,
SCENARIO_DIR,
HEIGHTMAP_DIR,
BASESET_DIR,
NEWGRF_DIR,
AI_DIR,
AI_LIBRARY_DIR,
GAME_DIR,
GAME_LIBRARY_DIR,
SCREENSHOT_DIR 1230 for (uint i = 0; i <
lengthof(default_subdirs); i++) {
1242 for (uint i = 0; i <
lengthof(dirs); i++) {
1258 for (; *filename !=
'\0'; filename++) {
1259 switch (*filename) {
1262 case ':':
case '\\':
case '*':
case '?':
case '/':
1263 case '<':
case '>':
case '|':
case '"':
1280 FILE *in = fopen(filename,
"rb");
1281 if (in ==
nullptr)
return nullptr;
1283 fseek(in, 0, SEEK_END);
1284 size_t len = ftell(in);
1285 fseek(in, 0, SEEK_SET);
1286 if (len > maxsize) {
1290 byte *mem = MallocT<byte>(len + 1);
1292 if (fread(mem, len, 1, in) != 1) {
1311 if (extension ==
nullptr)
return true;
1313 const char *ext = strrchr(filename, extension[0]);
1314 return ext !=
nullptr && strcasecmp(ext, extension) == 0;
1326 static uint
ScanPath(
FileScanner *fs,
const char *extension,
const char *path,
size_t basepath_length,
bool recursive)
1328 extern bool FiosIsValidFile(
const char *path,
const struct dirent *ent,
struct stat *sb);
1332 struct dirent *dirent;
1335 if (path ==
nullptr || (dir =
ttd_opendir(path)) ==
nullptr)
return 0;
1337 while ((dirent = readdir(dir)) !=
nullptr) {
1338 const char *d_name =
FS2OTTD(dirent->d_name);
1341 if (!FiosIsValidFile(path, dirent, &sb))
continue;
1345 if (S_ISDIR(sb.st_mode)) {
1347 if (!recursive)
continue;
1348 if (strcmp(d_name,
".") == 0 || strcmp(d_name,
"..") == 0)
continue;
1350 num +=
ScanPath(fs, extension, filename, basepath_length, recursive);
1351 }
else if (S_ISREG(sb.st_mode)) {
1371 const char *
filename = (*tar).first.c_str();
1392 char path[MAX_PATH];
1393 TarFileList::iterator tar;
1400 FioAppendDirectory(path,
lastof(path), sp, sd);
1401 num +=
ScanPath(
this, extension, path, strlen(path), recursive);
1405 FOR_ALL_TARS(tar, sd) {
1406 num +=
ScanTar(
this, extension, tar);
1412 num += this->Scan(extension,
OLD_GM_DIR, tars, recursive);
1415 num += this->Scan(extension,
OLD_DATA_DIR, tars, recursive);
1434 char path[MAX_PATH];
1437 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.