DOSFS_DoGetFullPathName: rewrite to return results like OSR2.
This commit is contained in:
parent
f93eb3e319
commit
d3b890f66d
173
files/dos_fs.c
173
files/dos_fs.c
|
@ -1086,102 +1086,121 @@ DWORD WINAPI GetLongPathNameW( LPCWSTR shortpath, LPWSTR longpath,
|
||||||
*
|
*
|
||||||
* Implementation of GetFullPathNameA/W.
|
* Implementation of GetFullPathNameA/W.
|
||||||
*
|
*
|
||||||
* Known discrepancies to Win95 OSR2 bon 000118
|
* bon@elektron 000331:
|
||||||
* "g:..\test should return G:\test
|
* A test for GetFullPathName with many patholotical case
|
||||||
* "..\..\..\..\test should return (Current drive):test
|
* gives now identical output for Wine and OSR2
|
||||||
* even when test is not existant
|
|
||||||
*/
|
*/
|
||||||
static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
|
static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
|
||||||
BOOL unicode )
|
BOOL unicode )
|
||||||
{
|
{
|
||||||
char buffer[MAX_PATHNAME_LEN];
|
|
||||||
int drive;
|
|
||||||
char *p;
|
|
||||||
char namelast;
|
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
DOS_FULL_NAME full_name;
|
||||||
|
char *p,*q;
|
||||||
|
const char * root;
|
||||||
|
char drivecur[]="c:.";
|
||||||
|
char driveletter=0;
|
||||||
|
int namelen,drive=0;
|
||||||
|
|
||||||
/* Address of the last byte in the buffer */
|
if ((strlen(name) >1)&& (name[1]==':'))
|
||||||
char *endbuf = buffer + sizeof(buffer) - 1;
|
/*drive letter given */
|
||||||
|
|
||||||
TRACE("converting '%s'\n", name );
|
|
||||||
|
|
||||||
if (!name || ((drive = DOSFS_GetPathDrive( &name )) == -1) )
|
|
||||||
{
|
{
|
||||||
SetLastError( ERROR_INVALID_PARAMETER );
|
driveletter = name[0];
|
||||||
|
}
|
||||||
|
if ((strlen(name) >2)&& (name[1]==':') &&
|
||||||
|
((name[2]=='\\') || (name[2]=='/')))
|
||||||
|
/*absolue path given */
|
||||||
|
{
|
||||||
|
lstrcpynA(full_name.short_name,name,MAX_PATHNAME_LEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (driveletter)
|
||||||
|
drivecur[0]=driveletter;
|
||||||
|
else
|
||||||
|
strcpy(drivecur,".");
|
||||||
|
if (!DOSFS_GetFullName( drivecur, FALSE, &full_name ))
|
||||||
|
{
|
||||||
|
FIXME("internal: error getting drive/path\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* find path that drive letter substitutes*/
|
||||||
p = buffer;
|
drive = (int)toupper(full_name.short_name[0]) -0x41;
|
||||||
*p++ = 'A' + drive;
|
root= DRIVE_GetRoot(drive);
|
||||||
*p++ = ':';
|
p= full_name.long_name +strlen(root);
|
||||||
*p++ = '\\';
|
/* append long name (= unix name) to drive */
|
||||||
if ((*name!='/') && (*name!='\\'))
|
lstrcpynA(full_name.short_name+2,p,MAX_PATHNAME_LEN-3);
|
||||||
|
/* append name to treat */
|
||||||
|
namelen= strlen(full_name.short_name);
|
||||||
|
p = (char*)name;
|
||||||
|
if (driveletter)
|
||||||
|
p += +2; /* skip drive name when appending */
|
||||||
|
if (namelen +2 + strlen(p) > MAX_PATHNAME_LEN)
|
||||||
{
|
{
|
||||||
/* Relative path or empty path */
|
FIXME("internal error: buffer too small\n");
|
||||||
lstrcpynA( p, DRIVE_GetDosCwd(drive), sizeof(buffer) - 4 );
|
|
||||||
if ( *p )
|
|
||||||
{
|
|
||||||
p += strlen(p);
|
|
||||||
*p++ = '\\';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*name)
|
|
||||||
{
|
|
||||||
while ((*name == '\\') || (*name == '/'))
|
|
||||||
name++;
|
|
||||||
if (*name == '.')
|
|
||||||
{
|
|
||||||
if (IS_END_OF_NAME(name[1]))
|
|
||||||
{
|
|
||||||
name++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
|
|
||||||
{
|
|
||||||
if (p == buffer + 3) {
|
|
||||||
/* no previous dir component */
|
|
||||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* skip previously added '\\' */
|
full_name.short_name[namelen++] ='\\';
|
||||||
p-=2;
|
full_name.short_name[namelen] = 0;
|
||||||
/* skip previous dir component */
|
lstrcpynA(full_name.short_name +namelen,p,MAX_PATHNAME_LEN-namelen);
|
||||||
while (*p != '\\')
|
|
||||||
p--;
|
|
||||||
p++;
|
|
||||||
|
|
||||||
name += 2;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
/* reverse all slashes */
|
||||||
while (!IS_END_OF_NAME(*name) && (p<endbuf) )
|
for (p=full_name.short_name;
|
||||||
*p++ = *name++;
|
p < full_name.short_name+strlen(full_name.short_name);
|
||||||
if ((p<endbuf) && ((*name == '\\') || (*name == '/'))) {
|
p++)
|
||||||
*p++='\\';
|
|
||||||
name++;
|
|
||||||
}
|
|
||||||
if ( p==endbuf && *name )
|
|
||||||
{
|
{
|
||||||
SetLastError( ERROR_PATH_NOT_FOUND );
|
if ( *p == '/' )
|
||||||
return 0;
|
*p = '\\';
|
||||||
}
|
}
|
||||||
}
|
/* Use memmove, as areas overlap*/
|
||||||
*p = '\0';
|
/* Delete .. */
|
||||||
/* Only return a trailing \\ if name does end in \\ // or :*/
|
while ((p = strstr(full_name.short_name,"\\..\\")))
|
||||||
namelast= name[strlen(name)-1];
|
|
||||||
if ( (namelast != '\\') && (namelast != '/')&& (namelast != ':') )
|
|
||||||
{
|
{
|
||||||
if(*(p-1) == '\\')
|
if (p > full_name.short_name+2)
|
||||||
*(p-1) = '\0';
|
{
|
||||||
|
*p = 0;
|
||||||
|
q = strrchr(full_name.short_name,'\\');
|
||||||
|
memmove(q+1,p+4,strlen(p+4)+1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memmove(full_name.short_name+3,p+4,strlen(p+4)+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((full_name.short_name[2]=='.')&&(full_name.short_name[3]=='.'))
|
||||||
|
{
|
||||||
|
/* This case istn't treated yet : c:..\test */
|
||||||
|
memmove(full_name.short_name+2,full_name.short_name+4,
|
||||||
|
strlen(full_name.short_name+4)+1);
|
||||||
|
}
|
||||||
|
/* Delete . */
|
||||||
|
while ((p = strstr(full_name.short_name,"\\.\\")))
|
||||||
|
{
|
||||||
|
*(p+1) = 0;
|
||||||
|
memmove(p+1,p+3,strlen(p+3));
|
||||||
}
|
}
|
||||||
if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING))
|
if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING))
|
||||||
CharUpperA( buffer );
|
CharUpperA( full_name.short_name );
|
||||||
|
namelen=strlen(full_name.short_name);
|
||||||
|
if (!strcmp(full_name.short_name+namelen-3,"\\.."))
|
||||||
|
{
|
||||||
|
/* one more starnge case: "c:\test\test1\.."
|
||||||
|
return "c:\test"*/
|
||||||
|
*(full_name.short_name+namelen-3)=0;
|
||||||
|
q = strrchr(full_name.short_name,'\\');
|
||||||
|
*q =0;
|
||||||
|
}
|
||||||
|
if (full_name.short_name[namelen-1]=='.')
|
||||||
|
full_name.short_name[(namelen--)-1] =0;
|
||||||
|
if (!driveletter)
|
||||||
|
if (full_name.short_name[namelen-1]=='\\')
|
||||||
|
full_name.short_name[(namelen--)-1] =0;
|
||||||
|
TRACE("got %s\n",full_name.short_name);
|
||||||
|
|
||||||
/* If the lpBuffer buffer is too small, the return value is the
|
/* If the lpBuffer buffer is too small, the return value is the
|
||||||
size of the buffer, in characters, required to hold the path
|
size of the buffer, in characters, required to hold the path
|
||||||
plus the terminating \0 (tested against win95osr, bon 001118)
|
plus the terminating \0 (tested against win95osr, bon 001118)
|
||||||
. */
|
. */
|
||||||
ret = strlen(buffer);
|
ret = strlen(full_name.short_name);
|
||||||
if (ret >= len )
|
if (ret >= len )
|
||||||
{
|
{
|
||||||
/* don't touch anything when the buffer is not large enough */
|
/* don't touch anything when the buffer is not large enough */
|
||||||
|
@ -1191,12 +1210,12 @@ static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (unicode)
|
if (unicode)
|
||||||
lstrcpynAtoW( (LPWSTR)result, buffer, len );
|
lstrcpynAtoW( (LPWSTR)result, full_name.short_name, len );
|
||||||
else
|
else
|
||||||
lstrcpynA( result, buffer, len );
|
lstrcpynA( result, full_name.short_name, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("returning '%s'\n", buffer );
|
TRACE("returning '%s'\n", full_name.short_name );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue