Skip to content

Commit bb509a4

Browse files
macdiceadunstan
authored andcommitted
Fix lstat() for broken junction points on Windows.
When using junction points to emulate symlinks on Windows, one edge case was not handled correctly by commit c5cb8f3: if a junction point is broken (pointing to a non-existent path), we'd report ENOENT. This doesn't break any known use case, but was noticed while developing a test suite for these functions and is fixed here for completeness. Also add translation ERROR_CANT_RESOLVE_FILENAME -> ENOENT, as that is one of the errors Windows can report for some kinds of broken paths. Discussion: https://postgr.es/m/CA%2BhUKG%2BajSQ_8eu2AogTncOnZ5me2D-Cn66iN_-wZnRjLN%2Bicg%40mail.gmail.com (cherry picked from commit 387803d) Author: Thomas Munro <tmunro@postgresql.org> Author: Alexandra Wang <alexandra.wang.oss@gmail.com>
1 parent ee21910 commit bb509a4

File tree

2 files changed

+28
-5
lines changed

2 files changed

+28
-5
lines changed

src/port/win32error.c

+6
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ static const struct
164164
},
165165
{
166166
ERROR_DELETE_PENDING, ENOENT
167+
},
168+
{
169+
ERROR_INVALID_NAME, ENOENT
170+
},
171+
{
172+
ERROR_CANT_RESOLVE_FILENAME, ENOENT
167173
}
168174
};
169175

src/port/win32stat.c

+22-5
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,30 @@ _pglstat64(const char *name, struct stat *buf)
127127

128128
hFile = pgwin32_open_handle(name, O_RDONLY, true);
129129
if (hFile == INVALID_HANDLE_VALUE)
130-
return -1;
131-
132-
ret = fileinfo_to_stat(hFile, buf);
130+
{
131+
if (errno == ENOENT)
132+
{
133+
/*
134+
* If it's a junction point pointing to a non-existent path, we'll
135+
* have ENOENT here (because pgwin32_open_handle does not use
136+
* FILE_FLAG_OPEN_REPARSE_POINT). In that case, we'll try again
137+
* with readlink() below, which will distinguish true ENOENT from
138+
* pseudo-symlink.
139+
*/
140+
memset(buf, 0, sizeof(*buf));
141+
ret = 0;
142+
}
143+
else
144+
return -1;
145+
}
146+
else
147+
ret = fileinfo_to_stat(hFile, buf);
133148

134149
/*
135150
* Junction points appear as directories to fileinfo_to_stat(), so we'll
136151
* need to do a bit more work to distinguish them.
137152
*/
138-
if (ret == 0 && S_ISDIR(buf->st_mode))
153+
if ((ret == 0 && S_ISDIR(buf->st_mode)) || hFile == INVALID_HANDLE_VALUE)
139154
{
140155
char next[MAXPGPATH];
141156
ssize_t size;
@@ -171,10 +186,12 @@ _pglstat64(const char *name, struct stat *buf)
171186
buf->st_mode &= ~S_IFDIR;
172187
buf->st_mode |= S_IFLNK;
173188
buf->st_size = size;
189+
ret = 0;
174190
}
175191
}
176192

177-
CloseHandle(hFile);
193+
if (hFile != INVALID_HANDLE_VALUE)
194+
CloseHandle(hFile);
178195
return ret;
179196
}
180197

0 commit comments

Comments
 (0)