DOSFS: non-existing directories in path names with ..

Mike McCormack mike at codeweavers.com
Fri Jan 16 04:47:40 CST 2004


Hi,

It seems that windows removes .. and it's parent directory from 
pathnames before verifying that a parent directory exists.

Mike


ChangeLog:
* fix pathnames with non-existing directories and ..
-------------- next part --------------
Index: files/dos_fs.c
===================================================================
RCS file: /home/wine/wine/files/dos_fs.c,v
retrieving revision 1.146
diff -u -r1.146 dos_fs.c
--- files/dos_fs.c	15 Jan 2004 01:48:44 -0000	1.146
+++ files/dos_fs.c	16 Jan 2004 10:19:08 -0000
@@ -1032,7 +1032,8 @@
  * The buffers pointed to by 'long_buf' and 'short_buf' must be
  * at least MAX_PATHNAME_LEN long.
  */
-BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full )
+static BOOL DOSFS_GetFullNameNoDots( LPCWSTR name, BOOL check_last,
+                                     DOS_FULL_NAME *full )
 {
     BOOL found;
     UINT flags;
@@ -1171,6 +1172,112 @@
     return TRUE;
 }
 
+#define DOSFS_ISSEPERATOR( ch ) ( ((ch)=='\\') || ((ch)=='/') )
+
+BOOL DOSFS_GetFullName( LPCWSTR name, BOOL check_last, DOS_FULL_NAME *full )
+{
+    LPWSTR szFullPath, p;
+    LPCWSTR str;
+    BOOL r;
+    const WCHAR dots[] = { '.','.','\\',0 };
+    int count, drive, len;
+
+    TRACE("%s\n", debugstr_w(name));
+
+    /* don't mess with unix path names */
+    if( strchrW(name,'/') )
+        return DOSFS_GetFullNameNoDots( name, check_last, full );
+
+    str = name;
+    drive = DOSFS_GetPathDrive( &str );
+    if( drive == -1 )
+        return FALSE;
+
+    /* make a full path */
+    if( !DOSFS_ISSEPERATOR( str[0] ) )
+    {
+        LPCWSTR cwd = DRIVE_GetDosCwd( drive );
+        len = strlenW(cwd) + strlenW(str) + 5;
+        szFullPath = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+        szFullPath[0] = drive + 'A';
+        szFullPath[1] = ':';
+        szFullPath[2] = '\\';
+        szFullPath[3] = 0;
+        strcatW( szFullPath, cwd );
+        strcatW( szFullPath, &dots[2] );
+        strcatW( szFullPath, str );
+    }
+    else
+    {
+        len = strlenW(name) + 1;
+        szFullPath = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+        strcpyW( szFullPath, name );
+    }
+
+    /* now remove the DOS style dots, starting after the drive letter */
+    p = szFullPath;
+    if( ( p[0] == 0 ) || ( p[1] != ':' ) )
+        ERR("Oops\n");
+    p += 2;
+    str = p;
+    count = 0;
+    do
+    {
+        /* copy one backslash to the destination string for each segment */
+        if( DOSFS_ISSEPERATOR( str[0] ) )
+            *p++ = *str++;
+        while( DOSFS_ISSEPERATOR( str[0] ) )
+            *str++;
+
+        if( str[0] == '.' )
+        {
+            /* single dot segments can just be skipped */
+            if( (str[1] == 0) || DOSFS_ISSEPERATOR(str[1]) )
+            {
+                str++;
+                continue;
+            }
+
+            /* 
+             * Double dot segments cancel the previous segment
+             * NB: We only remove DOS type ..\ not unix ../
+             *     because each segment in a unix path must exist.
+             */
+            if( ( str[1] == '.' ) && 
+                ( (str[2] == 0) || DOSFS_ISSEPERATOR(str[2]) ) )
+            {
+                if( !count-- )
+                {
+                    SetLastError( ERROR_FILE_NOT_FOUND );
+                    return FALSE;
+                }
+                str += 2;
+                p--;
+                if( DOSFS_ISSEPERATOR(*p) )
+                    p--;
+                while( (p>szFullPath) && !DOSFS_ISSEPERATOR(*p) )
+                    p--;
+                continue;
+            }
+        }
+
+        /* other segments can be copied as they are */
+        while( str[0] && !DOSFS_ISSEPERATOR(str[0]) )
+            *p++ = *str++;
+        count++;
+    }
+    while( *str );
+    *p = 0;
+
+    TRACE("Path -> %s\n", debugstr_w(szFullPath));
+
+    r = DOSFS_GetFullNameNoDots( szFullPath, check_last, full );
+    HeapFree( GetProcessHeap(), 0, szFullPath );
+
+    return r;
+}
+
+#undef DOSFS_ISSEPERATOR
 
 /***********************************************************************
  *           DOSFS_DoGetFullPathName


More information about the wine-patches mailing list