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;
537 CreateDirectory(
OTTD2FS(name),
nullptr);
538 #elif defined(OS2) && !defined(__INNOTEK_LIBC__) 554 size_t s = strlen(buf);
557 if (s != 0 && buf[s - 1] != PATHSEPCHAR) {
558 if (&buf[s] >= last)
return false;
560 seprintf(buf + s, last,
"%c", PATHSEPCHAR);
566 static void TarAddLink(
const std::string &srcParam,
const std::string &destParam,
Subdirectory subdir)
568 std::string src = srcParam;
569 std::string dest = destParam;
571 std::transform(src.begin(), src.end(), src.begin(), tolower);
572 std::transform(dest.begin(), dest.end(), dest.begin(), tolower);
574 TarFileList::iterator dest_file = _tar_filelist[subdir].find(dest);
575 if (dest_file != _tar_filelist[subdir].end()) {
577 _tar_filelist[subdir].insert(TarFileList::value_type(src, dest_file->second));
581 const std::string src_path = ((*src.rbegin() == PATHSEPCHAR) ? src : src + PATHSEPCHAR);
582 const std::string dst_path = (dest.length() == 0 ?
"" : ((*dest.rbegin() == PATHSEPCHAR) ? dest : dest + PATHSEPCHAR));
583 _tar_linklist[subdir].insert(TarLinkList::value_type(src_path, dst_path));
598 #if (PATHSEPCHAR != '/') 599 for (
char *n = name; *n !=
'\0'; n++)
if (*n ==
'/') *n = PATHSEPCHAR;
610 _tar_filelist[sd].clear();
611 _tar_list[sd].clear();
612 uint num = this->Scan(
".tar", sd,
false);
619 DEBUG(misc, 1,
"Scanning for tars");
640 DEBUG(misc, 1,
"Scan complete, found %d files", num);
653 return this->AddFile(filename, 0);
659 assert(tar_filename ==
nullptr);
684 TarList::iterator it = _tar_list[this->subdir].find(filename);
685 if (it != _tar_list[this->subdir].end())
return false;
687 FILE *f = fopen(filename,
"rb");
692 if (f ==
nullptr)
return false;
694 const char *dupped_filename =
stredup(filename);
695 _tar_list[this->subdir][
filename].filename = dupped_filename;
696 _tar_list[this->subdir][
filename].dirname =
nullptr;
701 char buf[
sizeof(th.name) + 1], *end;
702 char name[
sizeof(th.prefix) + 1 +
sizeof(th.name) + 1];
703 char link[
sizeof(th.linkname) + 1];
704 char dest[
sizeof(th.prefix) + 1 +
sizeof(th.name) + 1 + 1 +
sizeof(th.linkname) + 1];
705 size_t num = 0,
pos = 0;
709 memset(&empty[0], 0,
sizeof(empty));
712 size_t num_bytes_read = fread(&th, 1, 512, f);
713 if (num_bytes_read != 512)
break;
714 pos += num_bytes_read;
717 if (strncmp(th.magic,
"ustar", 5) != 0 && memcmp(&th.magic, &empty[0], 512 - offsetof(TarHeader, magic)) != 0) {
719 if (memcmp(&th, &empty[0], 512) == 0)
continue;
721 DEBUG(misc, 0,
"The file '%s' isn't a valid tar-file", filename);
729 if (th.prefix[0] !=
'\0') {
739 size_t skip = strtoul(buf, &end, 8);
741 switch (th.typeflag) {
745 if (skip == 0)
break;
747 if (strlen(name) == 0)
break;
751 entry.tar_filename = dupped_filename;
753 entry.position =
pos;
758 DEBUG(misc, 6,
"Found file in tar: %s (" PRINTF_SIZE
" bytes, " PRINTF_SIZE
" offset)", name, skip,
pos);
759 if (_tar_filelist[this->subdir].insert(TarFileList::value_type(name, entry)).second) num++;
769 if (strlen(name) == 0 || strlen(link) == 0)
break;
776 if (link[0] == PATHSEPCHAR) {
777 DEBUG(misc, 1,
"Ignoring absolute link in tar: %s -> %s", name, link);
784 char *destpos = strrchr(dest, PATHSEPCHAR);
785 if (destpos ==
nullptr) destpos = dest;
789 while (*pos !=
'\0') {
790 char *next = strchr(pos, PATHSEPCHAR);
791 if (next ==
nullptr) {
792 next = pos + strlen(pos);
798 if (strcmp(pos,
".") == 0) {
800 }
else if (strcmp(pos,
"..") == 0) {
802 if (dest[0] ==
'\0') {
803 DEBUG(misc, 1,
"Ignoring link pointing outside of data directory: %s -> %s", name, link);
809 destpos = strrchr(dest, PATHSEPCHAR);
810 if (destpos ==
nullptr) destpos = dest;
814 if (destpos != dest) destpos =
strecpy(destpos, PATHSEP,
lastof(dest));
818 if (destpos >=
lastof(dest)) {
819 DEBUG(misc, 0,
"The length of a link in tar-file '%s' is too large (malformed?)", filename);
828 DEBUG(misc, 6,
"Found link in tar: %s -> %s", name, dest);
829 links.insert(TarLinkList::value_type(name, dest));
839 DEBUG(misc, 6,
"Found dir in tar: %s", name);
840 if (_tar_list[this->subdir][filename].dirname ==
nullptr) _tar_list[this->subdir][
filename].dirname =
stredup(name);
849 skip =
Align(skip, 512);
850 if (fseek(f, skip, SEEK_CUR) < 0) {
851 DEBUG(misc, 0,
"The file '%s' can't be read as a valid tar-file", filename);
858 DEBUG(misc, 1,
"Found tar '%s' with " PRINTF_SIZE
" new files", filename, num);
870 for (TarLinkList::iterator link = links.begin(); link != links.end(); link++) {
871 const std::string &src = link->first;
872 const std::string &dest = link->second;
873 TarAddLink(src, dest, this->subdir);
888 TarList::iterator it = _tar_list[subdir].find(tar_filename);
890 if (it == _tar_list[subdir].end())
return false;
892 const char *dirname = (*it).second.dirname;
895 if (dirname ==
nullptr)
return false;
899 char *p = strrchr(filename, PATHSEPCHAR);
901 if (p ==
nullptr)
return false;
905 DEBUG(misc, 8,
"Extracting %s to directory %s", tar_filename, filename);
908 for (TarFileList::iterator it2 = _tar_filelist[subdir].begin(); it2 != _tar_filelist[subdir].end(); it2++) {
909 if (strcmp((*it2).second.tar_filename, tar_filename) != 0)
continue;
913 DEBUG(misc, 9,
" extracting %s", filename);
919 DEBUG(misc, 6,
"Extracting %s failed; could not open %s", filename, tar_filename);
924 FILE *out = fopen(filename,
"wb");
925 if (out ==
nullptr) {
926 DEBUG(misc, 6,
"Extracting %s failed; could not open %s", filename, filename);
934 for (; to_copy != 0; to_copy -= read) {
935 read = fread(buffer, 1,
min(to_copy,
lengthof(buffer)), in);
936 if (read <= 0 || fwrite(buffer, 1, read, out) != read)
break;
944 DEBUG(misc, 6,
"Extracting %s failed; still %i bytes to copy", filename, (
int)to_copy);
949 DEBUG(misc, 9,
" extraction successful");
974 bool success =
false;
976 char *app_bundle = strchr(tmp,
'.');
977 while (app_bundle !=
nullptr && strncasecmp(app_bundle,
".app", 4) != 0) app_bundle = strchr(&app_bundle[1],
'.');
979 if (app_bundle !=
nullptr) *app_bundle =
'\0';
981 char *s = strrchr(tmp, PATHSEPCHAR);
984 if (chdir(tmp) != 0) {
985 DEBUG(misc, 0,
"Directory with the binary does not exist?");
1027 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1028 const char *xdg_data_home = xdgDataHome(
nullptr);
1030 PERSONAL_DIR[0] ==
'.' ? &PERSONAL_DIR[1] : PERSONAL_DIR);
1031 free(xdg_data_home);
1036 #if defined(OS2) || !defined(WITH_PERSONAL_DIR) 1041 find_directory(B_USER_SETTINGS_DIRECTORY, &path);
1042 const char *homedir =
stredup(path.Path());
1048 const char *homedir = getenv(
"HOME");
1049 if (homedir !=
nullptr) {
1053 if (homedir ==
nullptr) {
1054 const struct passwd *pw = getpwuid(getuid());
1055 homedir = (pw ==
nullptr) ?
nullptr :
stredup(pw->pw_dir);
1059 if (homedir !=
nullptr) {
1061 seprintf(tmp,
lastof(tmp),
"%s" PATHSEP
"%s", homedir, PERSONAL_DIR);
1071 #if defined(WITH_SHARED_DIR) 1079 if (getcwd(tmp, MAX_PATH) ==
nullptr) *tmp =
'\0';
1087 if (getcwd(tmp, MAX_PATH) ==
nullptr) *tmp =
'\0';
1097 DEBUG(misc, 0,
"Failed to return to working directory!");
1101 #if !defined(GLOBAL_DATA_DIR) 1109 extern void cocoaSetApplicationBundleDir();
1110 cocoaSetApplicationBundleDir();
1129 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1130 char config_home[MAX_PATH];
1132 const char *xdg_config_home = xdgConfigHome(
nullptr);
1133 seprintf(config_home,
lastof(config_home),
"%s" PATHSEP
"%s", xdg_config_home,
1134 PERSONAL_DIR[0] ==
'.' ? &PERSONAL_DIR[1] : PERSONAL_DIR);
1135 free(xdg_config_home);
1149 char *end = strrchr(config_dir, PATHSEPCHAR);
1150 if (end ==
nullptr) {
1151 config_dir[0] =
'\0';
1156 char personal_dir[MAX_PATH];
1158 char *end = strrchr(personal_dir, PATHSEPCHAR);
1159 if (end !=
nullptr) end[1] =
'\0';
1160 config_dir =
stredup(personal_dir);
1163 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1165 config_dir = config_home;
1167 static const Searchpath new_openttd_cfg_order[] = {
1171 config_dir =
nullptr;
1172 for (uint i = 0; i <
lengthof(new_openttd_cfg_order); i++) {
1178 assert(config_dir !=
nullptr);
1184 DEBUG(misc, 3,
"%s found as config directory", config_dir);
1187 extern char *_hotkeys_file;
1188 _hotkeys_file =
str_fmt(
"%shotkeys.cfg", config_dir);
1190 _windows_file =
str_fmt(
"%swindows.cfg", config_dir);
1192 #if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) 1193 if (config_dir == config_home) {
1205 #if defined(WITH_PERSONAL_DIR) 1213 SAVE_DIR,
AUTOSAVE_DIR,
SCENARIO_DIR,
HEIGHTMAP_DIR,
BASESET_DIR,
NEWGRF_DIR,
AI_DIR,
AI_LIBRARY_DIR,
GAME_DIR,
GAME_LIBRARY_DIR,
SCREENSHOT_DIR 1216 for (uint i = 0; i <
lengthof(default_subdirs); i++) {
1228 for (uint i = 0; i <
lengthof(dirs); i++) {
1244 for (; *filename !=
'\0'; filename++) {
1245 switch (*filename) {
1248 case ':':
case '\\':
case '*':
case '?':
case '/':
1249 case '<':
case '>':
case '|':
case '"':
1266 FILE *in = fopen(filename,
"rb");
1267 if (in ==
nullptr)
return nullptr;
1269 fseek(in, 0, SEEK_END);
1270 size_t len = ftell(in);
1271 fseek(in, 0, SEEK_SET);
1272 if (len > maxsize) {
1276 byte *mem = MallocT<byte>(len + 1);
1278 if (fread(mem, len, 1, in) != 1) {
1297 if (extension ==
nullptr)
return true;
1299 const char *ext = strrchr(filename, extension[0]);
1300 return ext !=
nullptr && strcasecmp(ext, extension) == 0;
1312 static uint
ScanPath(
FileScanner *fs,
const char *extension,
const char *path,
size_t basepath_length,
bool recursive)
1314 extern bool FiosIsValidFile(
const char *path,
const struct dirent *ent,
struct stat *sb);
1318 struct dirent *dirent;
1321 if (path ==
nullptr || (dir =
ttd_opendir(path)) ==
nullptr)
return 0;
1323 while ((dirent = readdir(dir)) !=
nullptr) {
1324 const char *d_name =
FS2OTTD(dirent->d_name);
1327 if (!FiosIsValidFile(path, dirent, &sb))
continue;
1331 if (S_ISDIR(sb.st_mode)) {
1333 if (!recursive)
continue;
1334 if (strcmp(d_name,
".") == 0 || strcmp(d_name,
"..") == 0)
continue;
1336 num +=
ScanPath(fs, extension, filename, basepath_length, recursive);
1337 }
else if (S_ISREG(sb.st_mode)) {
1357 const char *
filename = (*tar).first.c_str();
1378 char path[MAX_PATH];
1379 TarFileList::iterator tar;
1386 FioAppendDirectory(path,
lastof(path), sp, sd);
1387 num +=
ScanPath(
this, extension, path, strlen(path), recursive);
1391 FOR_ALL_TARS(tar, sd) {
1392 num +=
ScanTar(
this, extension, tar);
1398 num += this->Scan(extension,
OLD_GM_DIR, tars, recursive);
1401 num += this->Scan(extension,
OLD_DATA_DIR, tars, recursive);
1420 char path[MAX_PATH];
1423 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.
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.