27 #include "table/strings.h" 32 static char *_fios_path;
33 static const char *_fios_path_last;
34 SortingBits _savegame_sort_order = SORT_BY_DATE | SORT_DESCENDING;
37 extern bool FiosIsRoot(
const char *path);
38 extern bool FiosIsValidFile(
const char *path,
const struct dirent *ent,
struct stat *sb);
39 extern bool FiosIsHiddenFile(
const struct dirent *ent);
40 extern void FiosGetDrives(
FileList &file_list);
41 extern bool FiosGetDiskFreeSpace(
const char *path, uint64 *tot);
44 extern void GetOldSaveGameName(
const char *file,
char *title,
const char *last);
56 if ((_savegame_sort_order & SORT_BY_NAME) == 0 && da->mtime != db->mtime) {
57 r = da->mtime < db->mtime ? -1 : 1;
59 r = strcasecmp(da->title, db->title);
62 if (_savegame_sort_order & SORT_DESCENDING) r = -r;
81 switch (abstract_filetype) {
111 if (strcmp(file, item->name) == 0)
return item;
112 if (strcmp(file, item->title) == 0)
return item;
117 int i = strtol(file, &endptr, 10);
118 if (file == endptr || *endptr !=
'\0') i = -1;
124 char long_file[MAX_PATH];
127 if (strcmp(long_file, item->name) == 0)
return item;
128 if (strcmp(long_file, item->title) == 0)
return item;
144 return FiosGetDiskFreeSpace(*path, total_free) ? STR_SAVELOAD_BYTES_FREE : STR_ERROR_UNABLE_TO_READ_DRIVE;
154 switch (item->type) {
155 case FIOS_TYPE_DRIVE:
156 #if defined(_WIN32) || defined(__OS2__) 157 seprintf(_fios_path, _fios_path_last,
"%c:" PATHSEP, item->title[0]);
161 case FIOS_TYPE_INVALID:
164 case FIOS_TYPE_PARENT: {
166 char *s = strrchr(_fios_path, PATHSEPCHAR);
167 if (s != NULL && s != _fios_path) {
170 s = strrchr(_fios_path, PATHSEPCHAR);
173 #if defined(__MORPHOS__) || defined(__AMIGAOS__) 175 }
else if ((s = strrchr(_fios_path,
':')) != NULL) {
183 strecat(_fios_path, item->name, _fios_path_last);
184 strecat(_fios_path, PATHSEP, _fios_path_last);
187 case FIOS_TYPE_DIRECT:
188 seprintf(_fios_path, _fios_path_last,
"%s", item->name);
192 case FIOS_TYPE_OLDFILE:
193 case FIOS_TYPE_SCENARIO:
194 case FIOS_TYPE_OLD_SCENARIO:
211 static void FiosMakeFilename(
char *buf,
const char *path,
const char *name,
const char *ext,
const char *last)
216 period = strrchr(name,
'.');
217 if (period != NULL && strcasecmp(period, ext) == 0) ext =
"";
218 #if defined(__MORPHOS__) || defined(__AMIGAOS__) 220 unsigned char sepchar = path[(strlen(path) - 1)];
222 if (sepchar !=
':' && sepchar !=
'/') {
223 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
225 seprintf(buf, last,
"%s%s%s", path, name, ext);
228 seprintf(buf, last,
"%s%s", name, ext);
231 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
243 const char *extension = (_game_mode == GM_EDITOR) ?
".scn" :
".sav";
273 return unlink(filename) == 0;
276 typedef FiosType fios_getlist_callback_proc(
SaveLoadOperation fop,
const char *filename,
const char *ext,
char *title,
const char *last);
283 fios_getlist_callback_proc *callback_proc;
293 fop(fop), callback_proc(callback_proc), file_list(file_list)
296 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename);
307 const char *ext = strrchr(filename,
'.');
308 if (ext == NULL)
return false;
311 fios_title[0] =
'\0';
313 FiosType type = this->callback_proc(this->fop, filename, ext, fios_title,
lastof(fios_title));
314 if (type == FIOS_TYPE_INVALID)
return false;
316 for (
const FiosItem *fios = file_list.Begin(); fios != file_list.End(); fios++) {
317 if (strcmp(fios->name, filename) == 0)
return false;
320 FiosItem *fios = file_list.Append();
323 if (_tstat(
OTTD2FS(filename), &sb) == 0) {
326 if (stat(filename, &sb) == 0) {
328 fios->mtime = sb.st_mtime;
337 const char *t = fios_title;
339 t = strrchr(filename, PATHSEPCHAR);
340 t = (t == NULL) ? filename : (t + 1);
359 struct dirent *dirent;
363 char d_name[
sizeof(fios->name)];
368 if (!FiosIsRoot(_fios_path)) {
369 fios = file_list.
Append();
370 fios->type = FIOS_TYPE_PARENT;
373 strecpy(fios->title,
".. (Parent directory)",
lastof(fios->title));
378 while ((dirent = readdir(dir)) != NULL) {
382 if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
383 (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
384 strcmp(d_name,
".") != 0 && strcmp(d_name,
"..") != 0) {
385 fios = file_list.
Append();
386 fios->type = FIOS_TYPE_DIR;
389 seprintf(fios->title,
lastof(fios->title),
"%s" PATHSEP
" (Directory)", d_name);
398 SortingBits order = _savegame_sort_order;
399 _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
401 _savegame_sort_order = order;
405 sort_start = file_list.
Length();
410 scanner.
Scan(NULL, _fios_path,
false);
412 scanner.
Scan(NULL, subdir,
true,
true);
418 FiosGetDrives(file_list);
438 if (f == NULL)
return;
440 size_t read = fread(title, 1, last - title, f);
441 assert(title + read <= last);
467 if (ext == NULL)
return FIOS_TYPE_INVALID;
469 if (strcasecmp(ext,
".sav") == 0) {
471 return FIOS_TYPE_FILE;
475 if (strcasecmp(ext,
".ss1") == 0 || strcasecmp(ext,
".sv1") == 0 ||
476 strcasecmp(ext,
".sv2") == 0) {
477 if (title != NULL) GetOldSaveGameName(file, title, last);
478 return FIOS_TYPE_OLDFILE;
482 return FIOS_TYPE_INVALID;
493 static char *fios_save_path = NULL;
494 static char *fios_save_path_last = NULL;
496 if (fios_save_path == NULL) {
497 fios_save_path = MallocT<char>(MAX_PATH);
498 fios_save_path_last = fios_save_path + MAX_PATH - 1;
499 FioGetDirectory(fios_save_path, fios_save_path_last,
SAVE_DIR);
502 _fios_path = fios_save_path;
503 _fios_path_last = fios_save_path_last;
525 if (strcasecmp(ext,
".scn") == 0) {
527 return FIOS_TYPE_SCENARIO;
531 if (strcasecmp(ext,
".sv0") == 0 || strcasecmp(ext,
".ss0") == 0 ) {
532 GetOldSaveGameName(file, title, last);
533 return FIOS_TYPE_OLD_SCENARIO;
537 return FIOS_TYPE_INVALID;
548 static char *fios_scn_path = NULL;
549 static char *fios_scn_path_last = NULL;
552 if (fios_scn_path == NULL) {
553 fios_scn_path = MallocT<char>(MAX_PATH);
554 fios_scn_path_last = fios_scn_path + MAX_PATH - 1;
555 FioGetDirectory(fios_scn_path, fios_scn_path_last,
SCENARIO_DIR);
558 _fios_path = fios_scn_path;
559 _fios_path_last = fios_scn_path_last;
561 char base_path[MAX_PATH];
568 static FiosType FiosGetHeightmapListCallback(
SaveLoadOperation fop,
const char *file,
const char *ext,
char *title,
const char *last)
578 if (strcasecmp(ext,
".png") == 0) type = FIOS_TYPE_PNG;
581 if (strcasecmp(ext,
".bmp") == 0) type = FIOS_TYPE_BMP;
583 if (type == FIOS_TYPE_INVALID)
return FIOS_TYPE_INVALID;
585 TarFileList::iterator it = _tar_filelist[
SCENARIO_DIR].find(file);
598 if (strncmp(buf, it->second.tar_filename, strlen(buf)) == 0) {
604 if (!match)
return FIOS_TYPE_INVALID;
619 static char *fios_hmap_path = NULL;
620 static char *fios_hmap_path_last = NULL;
622 if (fios_hmap_path == NULL) {
623 fios_hmap_path = MallocT<char>(MAX_PATH);
624 fios_hmap_path_last = fios_hmap_path + MAX_PATH - 1;
625 FioGetDirectory(fios_hmap_path, fios_hmap_path_last,
HEIGHTMAP_DIR);
628 _fios_path = fios_hmap_path;
629 _fios_path_last = fios_hmap_path_last;
631 char base_path[MAX_PATH];
635 FiosGetFileList(fop, &FiosGetHeightmapListCallback, subdir, file_list);
644 static char *fios_screenshot_path = NULL;
646 if (fios_screenshot_path == NULL) {
647 fios_screenshot_path = MallocT<char>(MAX_PATH);
648 FioGetDirectory(fios_screenshot_path, fios_screenshot_path + MAX_PATH - 1,
SCREENSHOT_DIR);
651 return fios_screenshot_path;
654 #if defined(ENABLE_NETWORK) 656 #include "3rdparty/md5/md5.h" 662 char filename[MAX_PATH];
666 return this->scenid == other.
scenid &&
667 memcmp(this->md5sum, other.
md5sum,
sizeof(this->md5sum)) == 0;
672 return !(*
this == other);
691 if (this->scanned && !rescan)
return;
694 this->scanned =
true;
697 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename)
700 if (f == NULL)
return false;
703 int fret = fscanf(f,
"%i", &
id.scenid);
705 if (fret != 1)
return false;
710 char basename[MAX_PATH];
717 *strrchr(basename,
'.') =
'\0';
719 if (f == NULL)
return false;
722 while ((len = fread(buffer, 1, (size >
sizeof(buffer)) ?
sizeof(buffer) : size, f)) != 0 && size != 0) {
724 checksum.Append(buffer, len);
726 checksum.Finish(
id.md5sum);
746 _scanner.
Scan(
false);
749 if (md5sum ? (memcmp(id->md5sum, ci->
md5sum,
sizeof(id->md5sum)) == 0)
FiosType
Elements of a file system that are recognized.
bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
Try to add a fios item set with the given filename.
AbstractFileType
The different abstract types of files that the system knows about.
Basic data to distinguish a scenario.
uint32 unique_id
Unique ID; either GRF ID or shortname.
Scanner to find the unique IDs of scenarios.
FiosType FiosGetSavegameListCallback(SaveLoadOperation fop, const char *file, const char *ext, char *title, const char *last)
Callback for FiosGetFileList.
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.
void FioFCloseFile(FILE *f)
Close a file in a safe way.
Structs, typedefs and macros used for TAR file handling.
void Clear()
Remove all items from the list.
static bool IsInsideMM(const T x, const uint min, const uint max)
Checks if a value is in an interval.
uint8 md5sum[16]
MD5 checksum of file.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
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.
#define FOR_ALL_SEARCHPATHS(sp)
Iterator for all the search paths.
Subdirectory of scenario for heightmaps.
Subdirectory for all screenshots.
const T * Begin() const
Get the pointer to the first item (const)
const FiosItem * Begin() const
Get a pointer to the first file information.
void FiosGetSavegameList(SaveLoadOperation fop, FileList &file_list)
Get a list of savegames.
Functions for Standard In/Out file operations.
#define lastof(x)
Get the last element of an fixed size array.
Simple vector template class.
Functions to make screenshots.
Searchpath
Types of searchpaths OpenTTD might use.
uint32 scenid
ID for the scenario (generated by content).
void FiosGetScenarioList(SaveLoadOperation fop, FileList &file_list)
Get a list of scenarios.
const T * End() const
Get the pointer behind the last valid item (const)
Deals with finding savegames.
StringID FiosGetDescText(const char **path, uint64 *total_free)
Get descriptive texts.
Helper for scanning for files with a given name.
const FiosItem * FindItem(const char *file)
Find file information of a file by its name from the file list.
SmallVector< FiosItem, 32 > files
The list of files.
bool HasScenario(const ContentInfo *ci, bool md5sum)
Check whether we've got a given scenario based on its unique ID.
FiosFileScanner(SaveLoadOperation fop, fios_getlist_callback_proc *callback_proc, FileList &file_list)
Create the scanner.
uint Length() const
Get the number of files in the list.
Functions related to low-level strings.
Base directory for all scenarios.
bool AddFile(const char *filename, size_t basepath_length, const char *tar_filename)
Add a file with the given filename.
const FiosItem * End() const
Get a pointer behind the last file information.
const char * FindScenario(const ContentInfo *ci, bool md5sum)
Find a given scenario based on its unique ID.
static ScenarioScanner _scanner
Scanner for scenarios.
bool scanned
Whether we've already scanned.
void FiosMakeSavegameName(char *buf, const char *name, const char *last)
Make a save game or scenario filename from a name.
uint Length() const
Get the number of items in the list.
bool operator!=(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Inverse of operator==().
void str_validate(char *str, const char *last, StringValidationSettings settings)
Scans the string for valid characters and if it finds invalid ones, replaces them with a question mar...
static void FiosMakeFilename(char *buf, const char *path, const char *name, const char *ext, const char *last)
Construct a filename from its components in destination buffer buf.
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.
Definition of base types and functions in a cross-platform compatible way.
A number of safeguards to prevent using unsafe methods.
void Scan(bool rescan)
Scan, but only if it's needed.
void ScanScenarios()
Force a (re)scan of the scenarios.
Base directory for all savegames.
bool operator==(const MultiMapIterator< Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare > &iter1, const MultiMapIterator< Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare > &iter2)
Compare two MultiMap iterators.
void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop)
Construct a file list with the given kind of files, for the stated purpose.
const FiosItem * Get(uint index) const
Get a pointer to the indicated file information.
FileList & file_list
Destination of the found files.
Part of the network protocol handling content distribution.
static void GetFileTitle(const char *file, char *title, const char *last, Subdirectory subdir)
Get the title of a file, which (if exists) is stored in a file named the same as the data file but wi...
int CDECL CompareFiosItems(const FiosItem *da, const FiosItem *db)
Compare two FiosItem's.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
byte md5sum[16]
The MD5 checksum.
const TCHAR * OTTD2FS(const char *name, bool console_cp)
Convert from OpenTTD's encoding to that of the local environment.
SaveLoadOperation
Operation performed on the file.
void Compact()
Compact the list down to the smallest block size boundary.
bool FiosDelete(const char *name)
Delete a file.
void FiosGetHeightmapList(SaveLoadOperation fop, FileList &file_list)
Get a list of heightmaps.
static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *callback_proc, Subdirectory subdir, FileList &file_list)
Fill the list of the files in a directory, according to some arbitrary rule.
void FiosMakeHeightmapName(char *buf, const char *name, const char *last)
Construct a filename for a height map.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Declarations for savegames operations.
List of file information.
const char * FiosBrowseTo(const FiosItem *item)
Browse to a new path based on the passed item, starting at #_fios_path.
static FiosType FiosGetScenarioListCallback(SaveLoadOperation fop, const char *file, const char *ext, char *title, const char *last)
Callback for FiosGetFileList.
Scanner to scan for a particular type of FIOS file.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
const char * GetCurrentScreenshotExtension()
Get filename extension of current screenshot file format.
static DIR * ttd_opendir(const char *path)
A wrapper around opendir() which will convert the string from OPENTTD encoding to that of the filesys...
SaveLoadOperation fop
The kind of file we are looking for.
FiosItem * Append()
Construct a new entry in the file list.
ScenarioScanner()
Initialise.
const char * FiosGetScreenshotDir()
Get the directory for screenshots.
static void QSortT(T *base, uint num, int(CDECL *comparator)(const T *, const T *), bool desc=false)
Type safe qsort()
Container for all important information about a piece of content.