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)