Fixed mounting a symlink to a real directory. stable-3.0
authorRyan C. Gordon <icculus@icculus.org>
Thu, 26 Oct 2017 14:21:36 -0400
branchstable-3.0
changeset 1624 e6921cdff303
parent 1623 2f3059329d19
child 1626 79692f33ebf0
Fixed mounting a symlink to a real directory.
(transplanted from f3459eaad51bbbed4fc2768c0ec65b3005a7f490)
src/physfs.c
src/physfs.h
src/physfs_archiver_dir.c
src/physfs_internal.h
src/physfs_platform_os2.c
src/physfs_platform_posix.c
src/physfs_platform_windows.c
--- a/src/physfs.c	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs.c	Thu Oct 26 14:21:36 2017 -0400
@@ -1595,7 +1595,7 @@
     assert(*endstr == dirsep);
     *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))
         {
--- a/src/physfs.h	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs.h	Thu Oct 26 14:21:36 2017 -0400
@@ -2176,11 +2176,15 @@
  *  or each other, for example.
  *
  * 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
  *  mountpoints and archive contents can overlap...the interpolation mechanism
  *  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
  *                   platform-dependent notation.
  *   \param mountPoint Location in the interpolated tree that this archive
--- a/src/physfs_archiver_dir.c	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs_archiver_dir.c	Thu Oct 26 14:21:36 2017 -0400
@@ -49,7 +49,8 @@
     const size_t seplen = 1;
 
     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)
         BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
 
@@ -97,7 +98,7 @@
     {
         const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
         PHYSFS_Stat statbuf;
-        __PHYSFS_platformStat(f, &statbuf);
+        __PHYSFS_platformStat(f, &statbuf, 0);  /* !!! FIXME: why are we stating here? */
         PHYSFS_setErrorCode(err);
     } /* if */
 
@@ -164,7 +165,7 @@
 
     CVT_TO_DEPENDENT(d, opaque, name);
     BAIL_IF_ERRPASS(!d, 0);
-    retval = __PHYSFS_platformStat(d, stat);
+    retval = __PHYSFS_platformStat(d, stat, 0);
     __PHYSFS_smallFree(d);
     return retval;
 } /* DIR_stat */
--- a/src/physfs_internal.h	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs_internal.h	Thu Oct 26 14:21:36 2017 -0400
@@ -549,11 +549,12 @@
  *
  * 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
- *  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.
  */
-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
--- a/src/physfs_platform_os2.c	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs_platform_os2.c	Thu Oct 26 14:21:36 2017 -0400
@@ -721,7 +721,7 @@
 } /* 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);
     FILESTATUS3 fs;
--- a/src/physfs_platform_posix.c	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs_platform_posix.c	Thu Oct 26 14:21:36 2017 -0400
@@ -296,11 +296,11 @@
 } /* __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;
-
-    BAIL_IF(lstat(filename, &statbuf) == -1, errcodeFromErrno(), 0);
+    const int rc = follow ? stat(fname, &statbuf) : lstat(fname, &statbuf);
+    BAIL_IF(rc == -1, errcodeFromErrno(), 0);
 
     if (S_ISREG(statbuf.st_mode))
     {
@@ -330,7 +330,7 @@
     st->createtime = statbuf.st_ctime;
     st->accesstime = statbuf.st_atime;
 
-    st->readonly = (access(filename, W_OK) == -1);
+    st->readonly = (access(fname, W_OK) == -1);
     return 1;
 } /* __PHYSFS_platformStat */
 
--- a/src/physfs_platform_windows.c	Mon Oct 23 14:58:54 2017 -0400
+++ b/src/physfs_platform_windows.c	Thu Oct 26 14:21:36 2017 -0400
@@ -960,7 +960,7 @@
 } /* 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;
     WCHAR *wstr = NULL;
@@ -975,7 +975,7 @@
     if (!rc)
         err = GetLastError();
     else  /* check for symlink while wstr is still available */
-        issymlink = isSymlink(wstr, winstat.dwFileAttributes);
+        issymlink = !follow && isSymlink(wstr, winstat.dwFileAttributes);
 
     __PHYSFS_smallFree(wstr);
     BAIL_IF(!rc, errcodeFromWinApiError(err), 0);