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:
157 seprintf(_fios_path, _fios_path_last, PATHSEP
"");
158 #elif defined(WIN32) || defined(__OS2__) 159 seprintf(_fios_path, _fios_path_last,
"%c:" PATHSEP, item->title[0]);
163 case FIOS_TYPE_INVALID:
166 case FIOS_TYPE_PARENT: {
168 char *s = strrchr(_fios_path, PATHSEPCHAR);
169 if (s != NULL && s != _fios_path) {
172 s = strrchr(_fios_path, PATHSEPCHAR);
175 #if defined(__MORPHOS__) || defined(__AMIGAOS__) 177 }
else if ((s = strrchr(_fios_path,
':')) != NULL) {
185 strecat(_fios_path, item->name, _fios_path_last);
186 strecat(_fios_path, PATHSEP, _fios_path_last);
189 case FIOS_TYPE_DIRECT:
190 seprintf(_fios_path, _fios_path_last,
"%s", item->name);
194 case FIOS_TYPE_OLDFILE:
195 case FIOS_TYPE_SCENARIO:
196 case FIOS_TYPE_OLD_SCENARIO:
213 static void FiosMakeFilename(
char *buf,
const char *path,
const char *name,
const char *ext,
const char *last)
218 period = strrchr(name,
'.');
219 if (period != NULL && strcasecmp(period, ext) == 0) ext =
"";
220 #if defined(__MORPHOS__) || defined(__AMIGAOS__) 222 unsigned char sepchar = path[(strlen(path) - 1)];
224 if (sepchar !=
':' && sepchar !=
'/') {
225 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
227 seprintf(buf, last,
"%s%s%s", path, name, ext);
230 seprintf(buf, last,
"%s%s", name, ext);
233 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
245 const char *extension = (_game_mode == GM_EDITOR) ?
".scn" :
".sav";
275 return unlink(filename) == 0;
278 typedef FiosType fios_getlist_callback_proc(
SaveLoadOperation fop,
const char *filename,
const char *ext,
char *title,
const char *last);
285 fios_getlist_callback_proc *callback_proc;
295 fop(fop), callback_proc(callback_proc), file_list(file_list)
298 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename);
309 const char *ext = strrchr(filename,
'.');
310 if (ext == NULL)
return false;
313 fios_title[0] =
'\0';
315 FiosType type = this->callback_proc(this->fop, filename, ext, fios_title,
lastof(fios_title));
316 if (type == FIOS_TYPE_INVALID)
return false;
318 for (
const FiosItem *fios = file_list.Begin(); fios != file_list.End(); fios++) {
319 if (strcmp(fios->name, filename) == 0)
return false;
322 FiosItem *fios = file_list.Append();
325 if (_tstat(
OTTD2FS(filename), &sb) == 0) {
328 if (stat(filename, &sb) == 0) {
330 fios->mtime = sb.st_mtime;
339 const char *t = fios_title;
341 t = strrchr(filename, PATHSEPCHAR);
342 t = (t == NULL) ? filename : (t + 1);
361 struct dirent *dirent;
365 char d_name[
sizeof(fios->name)];
370 if (!FiosIsRoot(_fios_path)) {
371 fios = file_list.
Append();
372 fios->type = FIOS_TYPE_PARENT;
375 strecpy(fios->title,
".. (Parent directory)",
lastof(fios->title));
380 while ((dirent = readdir(dir)) != NULL) {
384 if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
385 (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
386 strcmp(d_name,
".") != 0 && strcmp(d_name,
"..") != 0) {
387 fios = file_list.
Append();
388 fios->type = FIOS_TYPE_DIR;
391 seprintf(fios->title,
lastof(fios->title),
"%s" PATHSEP
" (Directory)", d_name);
400 SortingBits order = _savegame_sort_order;
401 _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
403 _savegame_sort_order = order;
407 sort_start = file_list.
Length();
412 scanner.
Scan(NULL, _fios_path,
false);
414 scanner.
Scan(NULL, subdir,
true,
true);
420 FiosGetDrives(file_list);
440 if (f == NULL)
return;
442 size_t read = fread(title, 1, last - title, f);
443 assert(title + read <= last);
469 if (ext == NULL)
return FIOS_TYPE_INVALID;
471 if (strcasecmp(ext,
".sav") == 0) {
473 return FIOS_TYPE_FILE;
477 if (strcasecmp(ext,
".ss1") == 0 || strcasecmp(ext,
".sv1") == 0 ||
478 strcasecmp(ext,
".sv2") == 0) {
479 if (title != NULL) GetOldSaveGameName(file, title, last);
480 return FIOS_TYPE_OLDFILE;
484 return FIOS_TYPE_INVALID;
495 static char *fios_save_path = NULL;
496 static char *fios_save_path_last = NULL;
498 if (fios_save_path == NULL) {
499 fios_save_path = MallocT<char>(MAX_PATH);
500 fios_save_path_last = fios_save_path + MAX_PATH - 1;
501 FioGetDirectory(fios_save_path, fios_save_path_last,
SAVE_DIR);
504 _fios_path = fios_save_path;
505 _fios_path_last = fios_save_path_last;
527 if (strcasecmp(ext,
".scn") == 0) {
529 return FIOS_TYPE_SCENARIO;
533 if (strcasecmp(ext,
".sv0") == 0 || strcasecmp(ext,
".ss0") == 0 ) {
534 GetOldSaveGameName(file, title, last);
535 return FIOS_TYPE_OLD_SCENARIO;
539 return FIOS_TYPE_INVALID;
550 static char *fios_scn_path = NULL;
551 static char *fios_scn_path_last = NULL;
554 if (fios_scn_path == NULL) {
555 fios_scn_path = MallocT<char>(MAX_PATH);
556 fios_scn_path_last = fios_scn_path + MAX_PATH - 1;
557 FioGetDirectory(fios_scn_path, fios_scn_path_last,
SCENARIO_DIR);
560 _fios_path = fios_scn_path;
561 _fios_path_last = fios_scn_path_last;
563 char base_path[MAX_PATH];
570 static FiosType FiosGetHeightmapListCallback(
SaveLoadOperation fop,
const char *file,
const char *ext,
char *title,
const char *last)
580 if (strcasecmp(ext,
".png") == 0) type = FIOS_TYPE_PNG;
583 if (strcasecmp(ext,
".bmp") == 0) type = FIOS_TYPE_BMP;
585 if (type == FIOS_TYPE_INVALID)
return FIOS_TYPE_INVALID;
587 TarFileList::iterator it = _tar_filelist[
SCENARIO_DIR].find(file);
600 if (strncmp(buf, it->second.tar_filename, strlen(buf)) == 0) {
606 if (!match)
return FIOS_TYPE_INVALID;
621 static char *fios_hmap_path = NULL;
622 static char *fios_hmap_path_last = NULL;
624 if (fios_hmap_path == NULL) {
625 fios_hmap_path = MallocT<char>(MAX_PATH);
626 fios_hmap_path_last = fios_hmap_path + MAX_PATH - 1;
627 FioGetDirectory(fios_hmap_path, fios_hmap_path_last,
HEIGHTMAP_DIR);
630 _fios_path = fios_hmap_path;
631 _fios_path_last = fios_hmap_path_last;
633 char base_path[MAX_PATH];
637 FiosGetFileList(fop, &FiosGetHeightmapListCallback, subdir, file_list);
646 static char *fios_screenshot_path = NULL;
648 if (fios_screenshot_path == NULL) {
649 fios_screenshot_path = MallocT<char>(MAX_PATH);
650 FioGetDirectory(fios_screenshot_path, fios_screenshot_path + MAX_PATH - 1,
SCREENSHOT_DIR);
653 return fios_screenshot_path;
656 #if defined(ENABLE_NETWORK) 658 #include "3rdparty/md5/md5.h" 664 char filename[MAX_PATH];
668 return this->scenid == other.
scenid &&
669 memcmp(this->md5sum, other.
md5sum,
sizeof(this->md5sum)) == 0;
674 return !(*
this == other);
693 if (this->scanned && !rescan)
return;
696 this->scanned =
true;
699 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename)
702 if (f == NULL)
return false;
705 int fret = fscanf(f,
"%i", &
id.scenid);
707 if (fret != 1)
return false;
712 char basename[MAX_PATH];
719 *strrchr(basename,
'.') =
'\0';
721 if (f == NULL)
return false;
724 while ((len = fread(buffer, 1, (size >
sizeof(buffer)) ?
sizeof(buffer) : size, f)) != 0 && size != 0) {
726 checksum.Append(buffer, len);
728 checksum.Finish(
id.md5sum);
748 _scanner.
Scan(
false);
751 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.