Skip to content

Commit d6a1f08

Browse files
macdicepull[bot]
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
1 parent 0fb471a commit d6a1f08

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

src/port/win32error.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ static const struct
167167
},
168168
{
169169
ERROR_INVALID_NAME, ENOENT
170+
},
171+
{
172+
ERROR_CANT_RESOLVE_FILENAME, ENOENT
170173
}
171174
};
172175

src/port/win32stat.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,30 @@ _pglstat64(const char *name, struct stat *buf)
125125

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

132147
/*
133148
* Junction points appear as directories to fileinfo_to_stat(), so we'll
134149
* need to do a bit more work to distinguish them.
135150
*/
136-
if (ret == 0 && S_ISDIR(buf->st_mode))
151+
if ((ret == 0 && S_ISDIR(buf->st_mode)) || hFile == INVALID_HANDLE_VALUE)
137152
{
138153
char next[MAXPGPATH];
139154
ssize_t size;
@@ -169,10 +184,12 @@ _pglstat64(const char *name, struct stat *buf)
169184
buf->st_mode &= ~S_IFDIR;
170185
buf->st_mode |= S_IFLNK;
171186
buf->st_size = size;
187+
ret = 0;
172188
}
173189
}
174190

175-
CloseHandle(hFile);
191+
if (hFile != INVALID_HANDLE_VALUE)
192+
CloseHandle(hFile);
176193
return ret;
177194
}
178195

0 commit comments

Comments
 (0)