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