Skip to content

Commit 4517358

Browse files
committed
Fix stat() for recursive junction points on Windows.
Commit c5cb8f3 supposed that we'd only ever have to follow one junction point in stat(), because we don't construct longer chains of them ourselves. When examining a parent directory supplied by the user, we should really be able to cope with longer chains, just in case someone has their system set up that way. Choose an arbitrary cap of 8, to match the minimum acceptable value of SYMLOOP_MAX in POSIX. Previously I'd avoided reporting ELOOP thinking Windows didn't have it, but it turns out that it does, so we can use the proper error number. Reviewed-by: Roman Zharkov <r.zharkov@postgrespro.ru> Discussion: https://postgr.es/m/CA%2BhUKGJ7JDGWYFt9%3D-TyJiRRy5q9TtPfqeKkneWDr1XPU1%2Biqw%40mail.gmail.com Discussion: https://postgr.es/m/CA%2BhUKG%2BajSQ_8eu2AogTncOnZ5me2D-Cn66iN_-wZnRjLN%2Bicg%40mail.gmail.com
1 parent f71007f commit 4517358

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

src/port/win32stat.c

+13-13
Original file line numberDiff line numberDiff line change
@@ -199,23 +199,33 @@ _pglstat64(const char *name, struct stat *buf)
199199
int
200200
_pgstat64(const char *name, struct stat *buf)
201201
{
202+
int loops = 0;
202203
int ret;
204+
char curr[MAXPGPATH];
203205

204206
ret = _pglstat64(name, buf);
205207

208+
strlcpy(curr, name, MAXPGPATH);
209+
206210
/* Do we need to follow a symlink (junction point)? */
207-
if (ret == 0 && S_ISLNK(buf->st_mode))
211+
while (ret == 0 && S_ISLNK(buf->st_mode))
208212
{
209213
char next[MAXPGPATH];
210214
ssize_t size;
211215

216+
if (++loops > 8)
217+
{
218+
errno = ELOOP;
219+
return -1;
220+
}
221+
212222
/*
213223
* _pglstat64() already called readlink() once to be able to fill in
214224
* st_size, and now we need to do it again to get the path to follow.
215225
* That could be optimized, but stat() on symlinks is probably rare
216226
* and this way is simple.
217227
*/
218-
size = readlink(name, next, sizeof(next));
228+
size = readlink(curr, next, sizeof(next));
219229
if (size < 0)
220230
{
221231
if (errno == EACCES &&
@@ -234,17 +244,7 @@ _pgstat64(const char *name, struct stat *buf)
234244
next[size] = 0;
235245

236246
ret = _pglstat64(next, buf);
237-
if (ret == 0 && S_ISLNK(buf->st_mode))
238-
{
239-
/*
240-
* We're only prepared to go one hop, because we only expect to
241-
* deal with the simple cases that we create. The error for too
242-
* many symlinks is supposed to be ELOOP, but Windows hasn't got
243-
* it.
244-
*/
245-
errno = EIO;
246-
return -1;
247-
}
247+
strcpy(curr, next);
248248
}
249249

250250
return ret;

0 commit comments

Comments
 (0)