CVS: winex/files dos_fs.c,1.39,1.40

[email protected] 29 Aug 2007 11:55:15 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/files dos_fs.c,1.39,1.40Update of /var/lib/cvsd/cvsroot/winex/files
In directory agravaine:/tmp/cvs-serv28532/files

Modified Files:
	dos_fs.c 
Log Message:
Ensure FindFirstFile*() always have . and .. as the first two items examined, as some games depend on this (even though MSDN states not to)


Index: dos_fs.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/files/dos_fs.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- dos_fs.c	31 Jul 2007 20:01:04 -0000	1.39
+++ dos_fs.c	29 Aug 2007 11:55:13 -0000	1.40
@@ -100,10 +100,14 @@
 #define GET_DRIVE(path) \
     (((path)[1] == ':') ? FILE_toupper((path)[0]) - 'A' : DOSFS_CurDrive)
 
+typedef enum {RDSTATE_START, RDSTATE_DOT, RDSTATE_DOTDOT,
+              RDSTATE_REST} ReadDirState_t;
+
 /* Directory info for DOSFS_ReadDir */
 typedef struct
 {
     DIR           *dir;
+    ReadDirState_t state;
 #ifdef VFAT_IOCTL_READDIR_BOTH
     int            fd;
     char           short_name[12];
@@ -123,6 +127,7 @@
     DOS_DIR *dir; /* only used by DOSFS_FindNext() */
 #ifdef CACHE_DIR_ENTRY
     off_t cur_dir_entry;
+    ReadDirState_t state;
 #endif
 } FIND_FIRST_INFO;
 
@@ -420,6 +425,8 @@
        directory and mask in several other places */
     if (!*path) path = "/";
 
+    dir->state = RDSTATE_START;
+
 #ifdef VFAT_IOCTL_READDIR_BOTH
     /* Check if the VFAT ioctl is supported on this directory */
 
@@ -472,6 +479,26 @@
 {
     struct dirent *dirent;
 
+    /* Why this? Some games depend on the returned list of names starting
+       with . and .., and this isn't guaranteed by UNIX filesystems
+       (although it normally is the case) */
+    if (dir->state == RDSTATE_START)
+    {
+       *long_name = ".";
+       *short_name = NULL;
+       dir->state = RDSTATE_DOT;
+       return TRUE;
+    }
+    else if (dir->state == RDSTATE_DOT)
+    {
+       *long_name = "..";
+       *short_name = NULL;
+       dir->state = RDSTATE_DOTDOT;
+       return TRUE;
+    }
+    else if (dir->state == RDSTATE_DOTDOT)
+       dir->state = RDSTATE_REST;
+
 #ifdef VFAT_IOCTL_READDIR_BOTH
     if (dir->fd != -1)
     {
@@ -676,6 +703,10 @@
 
     while ((ret = DOSFS_ReadDir( dir, &long_name, &short_name )))
     {
+       if ((dir->state == RDSTATE_REST) &&
+           (!strcmp (long_name, ".") || !strcmp (long_name, "..")))
+          continue;
+
        /* Apple's case-insensitive, so this will have been caught by
           the earlier stat optimization */
 #ifndef __APPLE__
@@ -1530,6 +1561,7 @@
 {
     DOS_DIR *pDir = DOSFS_OpenDir (pInfo->path);
 
+    pDir->state = pInfo->state;
 
    /* Seek to the place where we were at before, since we no longer
     * cache the directory pointer with FindFirstFile and friends.
@@ -1574,6 +1606,8 @@
  */
 static void DOSFS_FindNextEx_CloseDir(FIND_FIRST_INFO *pInfo, DOS_DIR *pDir)
 {
+    pInfo->state = pDir->state;
+
     /* Cache the current directory pointer location. This has a different semantics 
      * depending on whether we are dealing with a DIR* or an fd */
     if (!pInfo->dir)
@@ -1671,6 +1705,10 @@
 
     while (DOSFS_ReadDir( DirPtr, &long_name, &short_name ))
     {
+        if ((DirPtr->state == RDSTATE_REST) &&
+            (!strcmp (long_name, ".") || !strcmp (long_name, "..")))
+            continue;
+
         info->cur_pos++;
 
         /* Don't return '.' and '..' in the root of the drive */
@@ -1789,6 +1827,7 @@
         info.cur_pos = 0;
 #ifdef CACHE_DIR_ENTRY
 	info.cur_dir_entry = -1;
+	info.state = RDSTATE_START;
 #endif
         info.dir = DOSFS_OpenDir( info.path );
     }
@@ -1879,6 +1918,7 @@
 #ifdef CACHE_DIR_ENTRY
              info->dir = NULL;
              info->cur_dir_entry = 0;
+             info->state = RDSTATE_START;
 #else
              info->dir = DOSFS_OpenDir (info->path);
 #endif
@@ -2544,6 +2584,7 @@
     info->cur_pos = 0;
 #ifdef CACHE_DIR_ENTRY
     info->dir = NULL;
+    info->state = RDSTATE_START;
 #else
     info->dir = DOSFS_OpenDir (info->path);
 #endif