unixfs: Only resolve the 'dosdevices' based symbol links in

UNIXFS_get_unix_path, but leave all others alone.
This commit is contained in:
Michael Jung 2006-01-31 12:20:58 +01:00 committed by Alexandre Julliard
parent eb893bdea3
commit 48ca838873
1 changed files with 25 additions and 65 deletions

View File

@ -129,6 +129,7 @@
#include <stdarg.h>
#include <limits.h>
#include <dirent.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@ -403,8 +404,8 @@ static BOOL UNIXFS_is_dos_device(const struct stat *statPath) {
/******************************************************************************
* UNIXFS_get_unix_path [Internal]
*
* Convert an absolute dos path to an absolute canonicalized unix path.
* Evaluate "/.", "/.." and symbolic links.
* Convert an absolute dos path to an absolute unix path.
* Evaluate "/.", "/.." and the symbolic links in $WINEPREFIX/dosdevices.
*
* PARAMS
* pszDosPath [I] An absolute dos path
@ -417,18 +418,32 @@ static BOOL UNIXFS_is_dos_device(const struct stat *statPath) {
static BOOL UNIXFS_get_unix_path(LPCWSTR pszDosPath, char *pszCanonicalPath)
{
char *pPathTail, *pElement, *pCanonicalTail, szPath[FILENAME_MAX], *pszUnixPath;
struct stat fileStat;
WCHAR wszDrive[] = { '?', ':', '\\', 0 };
int cDriveSymlinkLen;
TRACE("(pszDosPath=%s, pszCanonicalPath=%p)\n", debugstr_w(pszDosPath), pszCanonicalPath);
if (!pszDosPath || pszDosPath[1] != ':')
return FALSE;
pszUnixPath = wine_get_unix_file_name(pszDosPath);
if (!pszUnixPath) return FALSE;
strcpy(szPath, pszUnixPath);
/* Get the canonicalized unix path corresponding to the drive letter. */
wszDrive[0] = pszDosPath[0];
pszUnixPath = wine_get_unix_file_name(wszDrive);
if (!pszUnixPath) return FALSE;
cDriveSymlinkLen = strlen(pszUnixPath);
pElement = canonicalize_file_name(pszUnixPath);
HeapFree(GetProcessHeap(), 0, pszUnixPath);
if (!pElement) return FALSE;
strcpy(szPath, pElement);
strcat(szPath, "/");
free(pElement);
/* Append the part relative to the drive symbolic link target. */
pszUnixPath = wine_get_unix_file_name(pszDosPath);
if (!pszUnixPath) return FALSE;
strcat(szPath, pszUnixPath + cDriveSymlinkLen);
HeapFree(GetProcessHeap(), 0, pszUnixPath);
/* pCanonicalTail always points to the end of the canonical path constructed
* thus far. pPathTail points to the still to be processed part of the input
* path. pElement points to the path element currently investigated.
@ -439,7 +454,6 @@ static BOOL UNIXFS_get_unix_path(LPCWSTR pszDosPath, char *pszCanonicalPath)
do {
char cTemp;
int cLinks = 0;
pElement = pPathTail;
pPathTail = strchr(pPathTail+1, '/');
@ -452,69 +466,15 @@ static BOOL UNIXFS_get_unix_path(LPCWSTR pszDosPath, char *pszCanonicalPath)
/* Skip "/." path elements */
if (!strcmp("/.", pElement)) {
*pPathTail = cTemp;
continue;
}
/* Remove last element in canonical path for "/.." elements, then skip. */
if (!strcmp("/..", pElement)) {
} else if (!strcmp("/..", pElement)) {
/* Remove last element in canonical path for "/.." elements, then skip. */
char *pTemp = strrchr(pszCanonicalPath, '/');
if (pTemp)
pCanonicalTail = pTemp;
*pCanonicalTail = '\0';
*pPathTail = cTemp;
continue;
}
/* lstat returns zero on success. */
if (lstat(szPath, &fileStat))
return FALSE;
if (S_ISLNK(fileStat.st_mode)) {
char szSymlink[FILENAME_MAX];
int cLinkLen, cTailLen;
/* Avoid infinite loop for recursive links. */
if (++cLinks > 64)
return FALSE;
cLinkLen = readlink(szPath, szSymlink, FILENAME_MAX);
if (cLinkLen < 0)
return FALSE;
*pPathTail = cTemp;
cTailLen = strlen(pPathTail);
if (szSymlink[0] == '/') {
/* Absolute link. Copy to szPath, concat remaining path and start all over. */
if (cLinkLen + cTailLen + 1 > FILENAME_MAX)
return FALSE;
/* Avoid double slashes. */
if (szSymlink[cLinkLen-1] == '/' && pPathTail[0] == '/') {
szSymlink[cLinkLen-1] = '\0';
cLinkLen--;
}
memcpy(szSymlink + cLinkLen, pPathTail, cTailLen + 1);
memcpy(szPath, szSymlink, cLinkLen + cTailLen + 1);
*pszCanonicalPath = '\0';
pCanonicalTail = pszCanonicalPath;
pPathTail = szPath;
} else {
/* Relative link. Expand into szPath and continue. */
char szTemp[FILENAME_MAX];
int cTailLen = strlen(pPathTail);
if (pElement - szPath + 1 + cLinkLen + cTailLen + 1 > FILENAME_MAX)
return FALSE;
memcpy(szTemp, pPathTail, cTailLen + 1);
memcpy(pElement + 1, szSymlink, cLinkLen);
memcpy(pElement + 1 + cLinkLen, szTemp, cTailLen + 1);
pPathTail = pElement;
}
} else {
/* Regular directory or file. Copy to canonical path */
/* Directory or file. Copy to canonical path */
if (pCanonicalTail - pszCanonicalPath + pPathTail - pElement + 1 > FILENAME_MAX)
return FALSE;