Commit 70c42d82 authored by Michael Wetherell's avatar Michael Wetherell Committed by Alexandre Julliard

Fix handling of unix absolute paths in DOSFS_GetFullName and

GetShortPathNameA. Handle '..' in paths in DRIVE_FindDriveRoot.
parent 757e7cb4
......@@ -866,6 +866,7 @@ static int DOSFS_GetPathDrive( const char **name )
*/
BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
{
BOOL unixabsolute = *name == '/';
BOOL found;
UINT flags;
char *p_l, *p_s, *root;
......@@ -893,7 +894,7 @@ BOOL DOSFS_GetFullName( LPCSTR name, BOOL check_last, DOS_FULL_NAME *full )
{
while ((*name == '\\') || (*name == '/')) name++;
}
else /* Relative path */
else if (!unixabsolute) /* Relative path */
{
lstrcpynA( root + 1, DRIVE_GetUnixCwd( full->drive ),
sizeof(full->long_name) - (root - full->long_name) - 1 );
......@@ -1026,6 +1027,7 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
DWORD sp = 0, lp = 0;
int tmplen, drive;
UINT flags;
BOOL unixabsolute = *longpath == '/';
TRACE("%s\n", debugstr_a(longpath));
......@@ -1053,6 +1055,13 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath,
if ( ( drive = DOSFS_GetPathDrive ( &longpath )) == -1 ) return 0;
flags = DRIVE_GetFlags ( drive );
if ( unixabsolute ) {
tmpshortpath[0] = drive + 'A';
tmpshortpath[1] = ':';
tmpshortpath[2] = '\\';
sp = 3;
}
while ( longpath[lp] ) {
/* check for path delimiters and reproduce them */
......
......@@ -374,53 +374,60 @@ int DRIVE_SetCurrentDrive( int drive )
*/
int DRIVE_FindDriveRoot( const char **path )
{
/* idea: check at all '/' positions.
* If the device and inode of that path is identical with the
* device and inode of the current drive then we found a solution.
* If there is another drive pointing to a deeper position in
* the file tree, we want to find that one, not the earlier solution.
/* Starting with the full path, check if the device and inode match any of
* the wine 'drives'. If not then remove the last path component and try
* again. If the last component was a '..' then skip a normal component
* since it's a directory that's ascended back out of.
*/
int drive, rootdrive = -1;
int drive, level, len;
char buffer[MAX_PATHNAME_LEN];
char *next = buffer;
const char *p = *path;
char *p;
struct stat st;
strcpy( buffer, "/" );
for (;;)
{
if (stat( buffer, &st ) || !S_ISDIR( st.st_mode )) break;
strcpy( buffer, *path );
while ((p = strchr( buffer, '\\' )) != NULL)
*p = '/';
len = strlen(buffer);
while (len > 0)
{
/* Find the drive */
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
if (stat( buffer, &st ) == 0 && S_ISDIR( st.st_mode ))
{
if (!DOSDrives[drive].root ||
(DOSDrives[drive].flags & DRIVE_DISABLED)) continue;
if ((DOSDrives[drive].dev == st.st_dev) &&
(DOSDrives[drive].ino == st.st_ino))
{
rootdrive = drive;
*path = p;
break;
}
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
{
if (!DOSDrives[drive].root ||
(DOSDrives[drive].flags & DRIVE_DISABLED))
continue;
if ((DOSDrives[drive].dev == st.st_dev) &&
(DOSDrives[drive].ino == st.st_ino))
{
TRACE( "%s -> drive %c:, root='%s', name='%s'\n",
*path, 'A' + drive, buffer, *path + len);
*path += len;
return drive;
}
}
}
/* Get the next path component */
*next++ = '/';
while ((*p == '/') || (*p == '\\')) p++;
if (!*p) break;
while (!IS_END_OF_NAME(*p)) *next++ = *p++;
*next = 0;
level = 0;
while (len > 0 && level < 1)
{
/* strip off a trailing slash */
while (len > 0 && buffer[len - 1] == '/')
buffer[--len] = 0;
/* find start of the last path component */
while (len > 0 && buffer[len - 1] != '/')
--len;
/* does removing it take us up a level? */
if (strcmp( buffer + len, "." ) != 0)
level += strcmp( buffer + len, ".." ) ? 1 : -1;
buffer[len] = 0;
}
}
*next = 0;
if (rootdrive != -1)
TRACE("%s -> drive %c:, root='%s', name='%s'\n",
buffer, 'A' + rootdrive, DOSDrives[rootdrive].root, *path );
return rootdrive;
return -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment