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]);
162 case FIOS_TYPE_INVALID:
165 case FIOS_TYPE_PARENT: {
167 char *s = strrchr(_fios_path, PATHSEPCHAR);
168 if (s != NULL && s != _fios_path) {
171 s = strrchr(_fios_path, PATHSEPCHAR);
174 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
176 }
else if ((s = strrchr(_fios_path,
':')) != NULL) {
184 strecat(_fios_path, item->name, _fios_path_last);
185 strecat(_fios_path, PATHSEP, _fios_path_last);
188 case FIOS_TYPE_DIRECT:
189 seprintf(_fios_path, _fios_path_last,
"%s", item->name);
193 case FIOS_TYPE_OLDFILE:
194 case FIOS_TYPE_SCENARIO:
195 case FIOS_TYPE_OLD_SCENARIO:
212 static void FiosMakeFilename(
char *buf,
const char *path,
const char *name,
const char *ext,
const char *last)
217 period = strrchr(name,
'.');
218 if (period != NULL && strcasecmp(period, ext) == 0) ext =
"";
219 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
221 unsigned char sepchar = path[(strlen(path) - 1)];
223 if (sepchar !=
':' && sepchar !=
'/') {
224 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
226 seprintf(buf, last,
"%s%s%s", path, name, ext);
229 seprintf(buf, last,
"%s%s", name, ext);
232 seprintf(buf, last,
"%s" PATHSEP
"%s%s", path, name, ext);
244 const char *extension = (_game_mode == GM_EDITOR) ?
".scn" :
".sav";
274 return unlink(filename) == 0;
277 typedef FiosType fios_getlist_callback_proc(
SaveLoadOperation fop,
const char *filename,
const char *ext,
char *title,
const char *last);
294 fop(fop), callback_proc(callback_proc), file_list(file_list)
297 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename);
308 const char *ext = strrchr(filename,
'.');
309 if (ext == NULL)
return false;
312 fios_title[0] =
'\0';
315 if (type == FIOS_TYPE_INVALID)
return false;
318 if (strcmp(fios->name, filename) == 0)
return false;
324 if (_tstat(
OTTD2FS(filename), &sb) == 0) {
327 if (stat(filename, &sb) == 0) {
329 fios->mtime = sb.st_mtime;
338 const char *t = fios_title;
340 t = strrchr(filename, PATHSEPCHAR);
341 t = (t == NULL) ? filename : (t + 1);
360 struct dirent *dirent;
364 char d_name[
sizeof(fios->name)];
369 if (!FiosIsRoot(_fios_path)) {
370 fios = file_list.
Append();
371 fios->type = FIOS_TYPE_PARENT;
374 strecpy(fios->title,
".. (Parent directory)",
lastof(fios->title));
379 while ((dirent = readdir(dir)) != NULL) {
383 if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) &&
384 (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
385 strcmp(d_name,
".") != 0 && strcmp(d_name,
"..") != 0) {
386 fios = file_list.
Append();
387 fios->type = FIOS_TYPE_DIR;
390 seprintf(fios->title,
lastof(fios->title),
"%s" PATHSEP
" (Directory)", d_name);
399 SortingBits order = _savegame_sort_order;
400 _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
402 _savegame_sort_order = order;
406 sort_start = file_list.
Length();
411 scanner.
Scan(NULL, _fios_path,
false);
413 scanner.
Scan(NULL, subdir,
true,
true);
419 FiosGetDrives(file_list);
439 if (f == NULL)
return;
441 size_t read = fread(title, 1, last - title, f);
442 assert(title + read <= last);
468 if (ext == NULL)
return FIOS_TYPE_INVALID;
470 if (strcasecmp(ext,
".sav") == 0) {
472 return FIOS_TYPE_FILE;
476 if (strcasecmp(ext,
".ss1") == 0 || strcasecmp(ext,
".sv1") == 0 ||
477 strcasecmp(ext,
".sv2") == 0) {
478 if (title != NULL) GetOldSaveGameName(file, title, last);
479 return FIOS_TYPE_OLDFILE;
483 return FIOS_TYPE_INVALID;
494 static char *fios_save_path = NULL;
495 static char *fios_save_path_last = NULL;
497 if (fios_save_path == NULL) {
498 fios_save_path = MallocT<char>(MAX_PATH);
499 fios_save_path_last = fios_save_path + MAX_PATH - 1;
500 FioGetDirectory(fios_save_path, fios_save_path_last,
SAVE_DIR);
503 _fios_path = fios_save_path;
504 _fios_path_last = fios_save_path_last;
526 if (strcasecmp(ext,
".scn") == 0) {
528 return FIOS_TYPE_SCENARIO;
532 if (strcasecmp(ext,
".sv0") == 0 || strcasecmp(ext,
".ss0") == 0 ) {
533 GetOldSaveGameName(file, title, last);
534 return FIOS_TYPE_OLD_SCENARIO;
538 return FIOS_TYPE_INVALID;
549 static char *fios_scn_path = NULL;
550 static char *fios_scn_path_last = NULL;
553 if (fios_scn_path == NULL) {
554 fios_scn_path = MallocT<char>(MAX_PATH);
555 fios_scn_path_last = fios_scn_path + MAX_PATH - 1;
556 FioGetDirectory(fios_scn_path, fios_scn_path_last,
SCENARIO_DIR);
559 _fios_path = fios_scn_path;
560 _fios_path_last = fios_scn_path_last;
562 char base_path[MAX_PATH];
579 if (strcasecmp(ext,
".png") == 0) type = FIOS_TYPE_PNG;
582 if (strcasecmp(ext,
".bmp") == 0) type = FIOS_TYPE_BMP;
584 if (type == FIOS_TYPE_INVALID)
return FIOS_TYPE_INVALID;
586 TarFileList::iterator it = _tar_filelist[
SCENARIO_DIR].find(file);
599 if (strncmp(buf, it->second.tar_filename, strlen(buf)) == 0) {
605 if (!match)
return FIOS_TYPE_INVALID;
620 static char *fios_hmap_path = NULL;
621 static char *fios_hmap_path_last = NULL;
623 if (fios_hmap_path == NULL) {
624 fios_hmap_path = MallocT<char>(MAX_PATH);
625 fios_hmap_path_last = fios_hmap_path + MAX_PATH - 1;
626 FioGetDirectory(fios_hmap_path, fios_hmap_path_last,
HEIGHTMAP_DIR);
629 _fios_path = fios_hmap_path;
630 _fios_path_last = fios_hmap_path_last;
632 char base_path[MAX_PATH];
636 FiosGetFileList(fop, &FiosGetHeightmapListCallback, subdir, file_list);
645 static char *fios_screenshot_path = NULL;
647 if (fios_screenshot_path == NULL) {
648 fios_screenshot_path = MallocT<char>(MAX_PATH);
649 FioGetDirectory(fios_screenshot_path, fios_screenshot_path + MAX_PATH - 1,
SCREENSHOT_DIR);
652 return fios_screenshot_path;
655 #if defined(ENABLE_NETWORK)
657 #include "3rdparty/md5/md5.h"
663 char filename[MAX_PATH];
667 return this->scenid == other.
scenid &&
668 memcmp(this->md5sum, other.
md5sum,
sizeof(this->md5sum)) == 0;
673 return !(*
this == other);
692 if (this->scanned && !rescan)
return;
695 this->scanned =
true;
698 bool AddFile(
const char *filename,
size_t basepath_length,
const char *tar_filename)
701 if (f == NULL)
return false;
704 int fret = fscanf(f,
"%i", &
id.scenid);
706 if (fret != 1)
return false;
711 char basename[MAX_PATH];
718 *strrchr(basename,
'.') =
'\0';
720 if (f == NULL)
return false;
723 while ((len = fread(buffer, 1, (size >
sizeof(buffer)) ?
sizeof(buffer) : size, f)) != 0 && size != 0) {
725 checksum.Append(buffer, len);
727 checksum.Finish(
id.md5sum);
747 _scanner.
Scan(
false);
750 if (md5sum ? (memcmp(id->md5sum, ci->
md5sum,
sizeof(id->md5sum)) == 0)