aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/port/win32stat.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/src/port/win32stat.c b/src/port/win32stat.c
index ce8d87093d8..e6553e4030b 100644
--- a/src/port/win32stat.c
+++ b/src/port/win32stat.c
@@ -199,23 +199,33 @@ _pglstat64(const char *name, struct stat *buf)
int
_pgstat64(const char *name, struct stat *buf)
{
+ int loops = 0;
int ret;
+ char curr[MAXPGPATH];
ret = _pglstat64(name, buf);
+ strlcpy(curr, name, MAXPGPATH);
+
/* Do we need to follow a symlink (junction point)? */
- if (ret == 0 && S_ISLNK(buf->st_mode))
+ while (ret == 0 && S_ISLNK(buf->st_mode))
{
char next[MAXPGPATH];
ssize_t size;
+ if (++loops > 8)
+ {
+ errno = ELOOP;
+ return -1;
+ }
+
/*
* _pglstat64() already called readlink() once to be able to fill in
* st_size, and now we need to do it again to get the path to follow.
* That could be optimized, but stat() on symlinks is probably rare
* and this way is simple.
*/
- size = readlink(name, next, sizeof(next));
+ size = readlink(curr, next, sizeof(next));
if (size < 0)
{
if (errno == EACCES &&
@@ -234,17 +244,7 @@ _pgstat64(const char *name, struct stat *buf)
next[size] = 0;
ret = _pglstat64(next, buf);
- if (ret == 0 && S_ISLNK(buf->st_mode))
- {
- /*
- * We're only prepared to go one hop, because we only expect to
- * deal with the simple cases that we create. The error for too
- * many symlinks is supposed to be ELOOP, but Windows hasn't got
- * it.
- */
- errno = EIO;
- return -1;
- }
+ strcpy(curr, next);
}
return ret;