Jump to content

Filesystem case sensitivity problems


Waywocket

Recommended Posts

I've been trying GemRB configured for tob, and had a number of problems that at first seemed to make no sense. Eventually, it turned out that GemRB was not finding files in the override folder, but using the old versions - most notably of start.chu, which does not have the window required by the start script, causing a crash as soon as the introductory movies are played. The reason for this appears to be due to the way case sensitive filesystems are handled (I'm trying to run the game from a ReiserFS filesystem BTW).

 

When CaseSensitive=1 is specified, ResolveFilePath is used to find the correct case for the filename, however ResolveFilePath is only called in the last stage of finding a file, after unsuccessfully trying the GemRB override, game override, etc. This means that if the files is in one of these directories, it is only found if the name is in the correct case.

 

So far I can see a number of possible fixes for this - or rather, variations on two ideas, which both have some problems. Making a call to ResolveFilePath in the FindIn and SearchIn macros (in KeyImp.cpp), just before calling fopen, didn't appear to work, though I've not yet given any thought as to why and it's probably fairly simple. Assuming this were to work however, it would also need to be called every other time fopen or _fopen is called, such as in FileStream.cpp. I'll have a look at doing this now...

 

Another option, on the other hand, would be to replace all calls to fopen with calls to gemrb_fopen, say. This could then be defined to be fopen on Win32, but otherwise could be something like this (formatting may go a bit off posted here):

FILE *fopen_nocase(const char *file, const char *mode)
{
   char full_path[PATH_MAX];
   FILE *value;
   char *base, *sep;
   char c;
   DIR *dirp;
   struct dirent *entry;

   value = fopen(file, mode);

   if (core && !core->CaseSensitive)
return value;

   strncpy(full_path, file, sizeof(full_path));
   base = full_path;

   if (*base == '/')
base++;
   
   while (( value == 0 ) && base)
   {
sep = strchr(base, '/');

if (sep)
    *sep = '\0';

c = *base;
*base = 0;
       dirp = opendir(full_path);

*base = c;

       if ( dirp )
{
           while ((entry=readdir(dirp)) != NULL)
    {
 if ( strcasecmp(entry->d_name, base) == 0 )
 {
                   strcpy(base, entry->d_name);
     break;
               }
           }
           closedir(dirp);

    if (sep)
 base = sep + 1;
    else
 base = NULL;
       }
else
    break;

if (sep)
    *sep = '/';

value = fopen(full_path, mode);
   }
   return value;
}

(Taken from http://cvs.icculus.org/cvs/loki_utils/loki_files.c?rev=1.9 )

That might mean the old functions for providing case insensitivity would no longer be required, though perhaps it would be too drastic a change for your liking. One benefit would be that the file paths themselves would never need to be modified, as fopen would do the work. This would enable a large number of const char*s to remain const, which the first option obviously does not allow.

Anyway, any comments?

Link to comment

*Sigh*

After all that, I can't figure out why the first fix I tried didn't work - since now it does :p . So it seems that all that's required to get this to work properly is one small change to KeyImp.cpp (it doesn't appear that you can use #ifdef within a macro, or it would be two lines):

Index: gemrb/plugins/KEYImporter/KeyImp.cpp
===================================================================
RCS file: /cvsroot/gemrb/gemrb/gemrb/plugins/KEYImporter/KeyImp.cpp,v
retrieving revision 1.55
diff -u -r1.55 KeyImp.cpp
--- gemrb/plugins/KEYImporter/KeyImp.cpp        30 Apr 2005 18:59:02 -0000      1.55
+++ gemrb/plugins/KEYImporter/KeyImp.cpp        19 Sep 2005 12:54:37 -0000
@@ -173,6 +173,7 @@
       return true;
}

+#ifdef WIN32
#define FindIn(BasePath, Path, ResRef, Type, foundMessage) \
{ \
       char p[_MAX_PATH], f[_MAX_PATH] = {0}; \
@@ -191,7 +192,52 @@
               return true; \
       } \
}
+#else
+#define FindIn(BasePath, Path, ResRef, Type, foundMessage) \
+{ \
+       char p[_MAX_PATH], f[_MAX_PATH] = {0}; \
+       strcpy(p, BasePath); \
+       strcat(p, Path); \
+       strcat(p, SPathDelimiter); \
+       strncpy(f, ResRef, 8); \
+       f[8] = 0; \
+       strcat(f, core->TypeExt(Type)); \
+       strlwr(f); \
+       strcat(p, f); \
+       ResolveFilePath(p);\
+       FILE * exist = fopen(p, "rb"); \
+       if(exist) { \
+               fclose(exist); \
+               printBracket(foundMessage, LIGHT_GREEN); printf("\n"); \
+               return true; \
+       } \
+}

+#endif
+
+#ifdef WIN32
+#define SearchIn(BasePath, Path, ResRef, Type, foundMessage) \
+{ \
+       char p[_MAX_PATH], f[_MAX_PATH] = {0}; \
+       strcpy(p, BasePath); \
+       strcat(p, Path); \
+       strcat(p, SPathDelimiter); \
+       strncpy(f, ResRef, 8); \
+       f[8] = 0; \
+       strcat(f, core->TypeExt(Type)); \
+       strlwr(f); \
+       strcat(p, f); \
+       FILE * exist = fopen(p, "rb"); \
+       if(exist) { \
+               fclose(exist); \
+               FileStream * fs = new FileStream(); \
+               if(!fs) return NULL; \
+               fs->Open(p, true); \
+               printBracket(foundMessage, LIGHT_GREEN); printf("\n"); \
+               return fs; \
+       } \
+}
+#else
#define SearchIn(BasePath, Path, ResRef, Type, foundMessage) \
{ \
       char p[_MAX_PATH], f[_MAX_PATH] = {0}; \
@@ -203,6 +249,7 @@
       strcat(f, core->TypeExt(Type)); \
       strlwr(f); \
       strcat(p, f); \
+       ResolveFilePath(p);\
       FILE * exist = fopen(p, "rb"); \
       if(exist) { \
               fclose(exist); \
@@ -213,6 +260,7 @@
               return fs; \
       } \
}
+#endif

bool KeyImp::HasResource(const char* resname, SClass_ID type)
{

 

Personally I'd quite like to rewrite ResolveFilePath using the method used by fopen_nocase in my previous post, since I find it easier to read, but that's largely by-the-by.

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...