Fixed mounting a symlink to a real directory.
(transplanted from f3459eaad51bbbed4fc2768c0ec65b3005a7f490)
This commit is contained in:
parent
b8aa7dab87
commit
a80261989e
|
@ -1595,7 +1595,7 @@ const char *PHYSFS_getPrefDir(const char *org, const char *app)
|
||||||
assert(*endstr == dirsep);
|
assert(*endstr == dirsep);
|
||||||
*endstr = '\0'; /* mask out the final dirsep for now. */
|
*endstr = '\0'; /* mask out the final dirsep for now. */
|
||||||
|
|
||||||
if (!__PHYSFS_platformStat(prefDir, &statbuf))
|
if (!__PHYSFS_platformStat(prefDir, &statbuf, 1))
|
||||||
{
|
{
|
||||||
for (ptr = strchr(prefDir, dirsep); ptr; ptr = strchr(ptr+1, dirsep))
|
for (ptr = strchr(prefDir, dirsep); ptr; ptr = strchr(ptr+1, dirsep))
|
||||||
{
|
{
|
||||||
|
|
|
@ -2176,11 +2176,15 @@ PHYSFS_DECL int PHYSFS_setAllocator(const PHYSFS_Allocator *allocator);
|
||||||
* or each other, for example.
|
* or each other, for example.
|
||||||
*
|
*
|
||||||
* The mountpoint does not need to exist prior to mounting, which is different
|
* The mountpoint does not need to exist prior to mounting, which is different
|
||||||
* than those familiar with the Unix concept of "mounting" may not expect.
|
* than those familiar with the Unix concept of "mounting" may expect.
|
||||||
* As well, more than one archive can be mounted to the same mountpoint, or
|
* As well, more than one archive can be mounted to the same mountpoint, or
|
||||||
* mountpoints and archive contents can overlap...the interpolation mechanism
|
* mountpoints and archive contents can overlap...the interpolation mechanism
|
||||||
* still functions as usual.
|
* still functions as usual.
|
||||||
*
|
*
|
||||||
|
* Specifying a symbolic link to an archive or directory is allowed here,
|
||||||
|
* regardless of the state of PHYSFS_permitSymbolicLinks(). That function
|
||||||
|
* only deals with symlinks inside the mounted directory or archive.
|
||||||
|
*
|
||||||
* \param newDir directory or archive to add to the path, in
|
* \param newDir directory or archive to add to the path, in
|
||||||
* platform-dependent notation.
|
* platform-dependent notation.
|
||||||
* \param mountPoint Location in the interpolated tree that this archive
|
* \param mountPoint Location in the interpolated tree that this archive
|
||||||
|
|
|
@ -49,7 +49,8 @@ static void *DIR_openArchive(PHYSFS_Io *io, const char *name,
|
||||||
const size_t seplen = 1;
|
const size_t seplen = 1;
|
||||||
|
|
||||||
assert(io == NULL); /* shouldn't create an Io for these. */
|
assert(io == NULL); /* shouldn't create an Io for these. */
|
||||||
BAIL_IF_ERRPASS(!__PHYSFS_platformStat(name, &st), NULL);
|
BAIL_IF_ERRPASS(!__PHYSFS_platformStat(name, &st, 1), NULL);
|
||||||
|
|
||||||
if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
|
if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
|
||||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ static PHYSFS_Io *doOpen(void *opaque, const char *name, const int mode)
|
||||||
{
|
{
|
||||||
const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
|
const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
|
||||||
PHYSFS_Stat statbuf;
|
PHYSFS_Stat statbuf;
|
||||||
__PHYSFS_platformStat(f, &statbuf);
|
__PHYSFS_platformStat(f, &statbuf, 0); /* !!! FIXME: why are we stating here? */
|
||||||
PHYSFS_setErrorCode(err);
|
PHYSFS_setErrorCode(err);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
|
@ -164,7 +165,7 @@ static int DIR_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
|
||||||
|
|
||||||
CVT_TO_DEPENDENT(d, opaque, name);
|
CVT_TO_DEPENDENT(d, opaque, name);
|
||||||
BAIL_IF_ERRPASS(!d, 0);
|
BAIL_IF_ERRPASS(!d, 0);
|
||||||
retval = __PHYSFS_platformStat(d, stat);
|
retval = __PHYSFS_platformStat(d, stat, 0);
|
||||||
__PHYSFS_smallFree(d);
|
__PHYSFS_smallFree(d);
|
||||||
return retval;
|
return retval;
|
||||||
} /* DIR_stat */
|
} /* DIR_stat */
|
||||||
|
|
|
@ -549,11 +549,12 @@ PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle);
|
||||||
*
|
*
|
||||||
* This needs to fill in all the fields of (stat). For fields that might not
|
* This needs to fill in all the fields of (stat). For fields that might not
|
||||||
* mean anything on a platform (access time, perhaps), choose a reasonable
|
* mean anything on a platform (access time, perhaps), choose a reasonable
|
||||||
* default.
|
* default. if (follow), we want to follow symlinks and stat what they
|
||||||
|
* link to and not the link itself.
|
||||||
*
|
*
|
||||||
* Return zero on failure, non-zero on success.
|
* Return zero on failure, non-zero on success.
|
||||||
*/
|
*/
|
||||||
int __PHYSFS_platformStat(const char *fn, PHYSFS_Stat *stat);
|
int __PHYSFS_platformStat(const char *fn, PHYSFS_Stat *stat, const int follow);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush any pending writes to disk. (opaque) should be cast to whatever data
|
* Flush any pending writes to disk. (opaque) should be cast to whatever data
|
||||||
|
|
|
@ -721,7 +721,7 @@ PHYSFS_sint64 os2TimeToUnixTime(const FDATE *date, const FTIME *time)
|
||||||
} /* os2TimeToUnixTime */
|
} /* os2TimeToUnixTime */
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *stat)
|
int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *stat, const int follow)
|
||||||
{
|
{
|
||||||
char *cpfname = cvtUtf8ToCodepage(filename);
|
char *cpfname = cvtUtf8ToCodepage(filename);
|
||||||
FILESTATUS3 fs;
|
FILESTATUS3 fs;
|
||||||
|
|
|
@ -296,11 +296,11 @@ int __PHYSFS_platformDelete(const char *path)
|
||||||
} /* __PHYSFS_platformDelete */
|
} /* __PHYSFS_platformDelete */
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st)
|
int __PHYSFS_platformStat(const char *fname, PHYSFS_Stat *st, const int follow)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
const int rc = follow ? stat(fname, &statbuf) : lstat(fname, &statbuf);
|
||||||
BAIL_IF(lstat(filename, &statbuf) == -1, errcodeFromErrno(), 0);
|
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
|
||||||
|
|
||||||
if (S_ISREG(statbuf.st_mode))
|
if (S_ISREG(statbuf.st_mode))
|
||||||
{
|
{
|
||||||
|
@ -330,7 +330,7 @@ int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st)
|
||||||
st->createtime = statbuf.st_ctime;
|
st->createtime = statbuf.st_ctime;
|
||||||
st->accesstime = statbuf.st_atime;
|
st->accesstime = statbuf.st_atime;
|
||||||
|
|
||||||
st->readonly = (access(filename, W_OK) == -1);
|
st->readonly = (access(fname, W_OK) == -1);
|
||||||
return 1;
|
return 1;
|
||||||
} /* __PHYSFS_platformStat */
|
} /* __PHYSFS_platformStat */
|
||||||
|
|
||||||
|
|
|
@ -960,7 +960,7 @@ static int isSymlink(const WCHAR *wpath, const DWORD attr)
|
||||||
} /* isSymlink */
|
} /* isSymlink */
|
||||||
|
|
||||||
|
|
||||||
int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st)
|
int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st, const int follow)
|
||||||
{
|
{
|
||||||
WIN32_FILE_ATTRIBUTE_DATA winstat;
|
WIN32_FILE_ATTRIBUTE_DATA winstat;
|
||||||
WCHAR *wstr = NULL;
|
WCHAR *wstr = NULL;
|
||||||
|
@ -975,7 +975,7 @@ int __PHYSFS_platformStat(const char *filename, PHYSFS_Stat *st)
|
||||||
if (!rc)
|
if (!rc)
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
else /* check for symlink while wstr is still available */
|
else /* check for symlink while wstr is still available */
|
||||||
issymlink = isSymlink(wstr, winstat.dwFileAttributes);
|
issymlink = !follow && isSymlink(wstr, winstat.dwFileAttributes);
|
||||||
|
|
||||||
__PHYSFS_smallFree(wstr);
|
__PHYSFS_smallFree(wstr);
|
||||||
BAIL_IF(!rc, errcodeFromWinApiError(err), 0);
|
BAIL_IF(!rc, errcodeFromWinApiError(err), 0);
|
||||||
|
|
Loading…
Reference in New Issue