Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc5cb8f3

Browse files
committed
Provide lstat() for Windows.
Junction points will be reported with S_ISLNK(x.st_mode), simulatingPOSIX lstat(). stat() will follow pseudo-symlinks, like in POSIX (butonly one level before giving up, unlike in POSIX).This completes a TODO left by commitbed9075.Tested-by: Andrew Dunstan <andrew@dunslane.net> (earlier version)Discussion:https://postgr.es/m/CA%2BhUKGLfOOeyZpm5ByVcAt7x5Pn-%3DxGRNCvgiUPVVzjFLtnY0w%40mail.gmail.com
1 parentfeb5935 commitc5cb8f3

File tree

2 files changed

+123
-5
lines changed

2 files changed

+123
-5
lines changed

‎src/include/port/win32_port.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,11 @@ struct stat/* This should match struct __stat64 */
278278

279279
externint_pgfstat64(intfileno,structstat*buf);
280280
externint_pgstat64(constchar*name,structstat*buf);
281+
externint_pglstat64(constchar*name,structstat*buf);
281282

282283
#definefstat(fileno,sb)_pgfstat64(fileno, sb)
283284
#definestat(path,sb)_pgstat64(path, sb)
284-
#definelstat(path,sb)_pgstat64(path, sb)
285+
#definelstat(path,sb)_pglstat64(path, sb)
285286

286287
/* These macros are not provided by older MinGW, nor by MSVC */
287288
#ifndefS_IRUSR
@@ -327,6 +328,21 @@ extern int_pgstat64(const char *name, struct stat *buf);
327328
#defineS_ISREG(m) (((m) & S_IFMT) == S_IFREG)
328329
#endif
329330

331+
/*
332+
* In order for lstat() to be able to report junction points as symlinks, we
333+
* need to hijack a bit in st_mode, since neither MSVC nor MinGW provides
334+
* S_ISLNK and there aren't any spare bits. We'll steal the one for character
335+
* devices, because we don't otherwise make use of those.
336+
*/
337+
#ifdefS_ISLNK
338+
#error "S_ISLNK is already defined"
339+
#endif
340+
#ifdefS_IFLNK
341+
#error "S_IFLNK is already defined"
342+
#endif
343+
#defineS_IFLNK S_IFCHR
344+
#defineS_ISLNK(m) (((m) & S_IFLNK) == S_IFLNK)
345+
330346
/*
331347
* Supplement to <fcntl.h>.
332348
* This is the same value as _O_NOINHERIT in the MS header file. This is

‎src/port/win32stat.c

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515

1616
#ifdefWIN32
1717

18+
#defineUMDF_USING_NTSTATUS
19+
1820
#include"c.h"
21+
#include"port/win32ntdll.h"
22+
1923
#include<windows.h>
2024

2125
/*
@@ -107,12 +111,10 @@ fileinfo_to_stat(HANDLE hFile, struct stat *buf)
107111
}
108112

109113
/*
110-
* Windows implementation of stat().
111-
*
112-
* This currently also implements lstat(), though perhaps that should change.
114+
* Windows implementation of lstat().
113115
*/
114116
int
115-
_pgstat64(constchar*name,structstat*buf)
117+
_pglstat64(constchar*name,structstat*buf)
116118
{
117119
/*
118120
* Our open wrapper will report STATUS_DELETE_PENDING as ENOENT. We
@@ -129,10 +131,110 @@ _pgstat64(const char *name, struct stat *buf)
129131

130132
ret=fileinfo_to_stat(hFile,buf);
131133

134+
/*
135+
* Junction points appear as directories to fileinfo_to_stat(), so we'll
136+
* need to do a bit more work to distinguish them.
137+
*/
138+
if (ret==0&&S_ISDIR(buf->st_mode))
139+
{
140+
charnext[MAXPGPATH];
141+
ssize_tsize;
142+
143+
/*
144+
* POSIX says we need to put the length of the target path into
145+
* st_size. Use readlink() to get it, or learn that this is not a
146+
* junction point.
147+
*/
148+
size=readlink(name,next,sizeof(next));
149+
if (size<0)
150+
{
151+
if (errno==EACCES&&
152+
pg_RtlGetLastNtStatus()==STATUS_DELETE_PENDING)
153+
{
154+
/* Unlinked underneath us. */
155+
errno=ENOENT;
156+
ret=-1;
157+
}
158+
elseif (errno==EINVAL)
159+
{
160+
/* It's not a junction point, nothing to do. */
161+
}
162+
else
163+
{
164+
/* Some other failure. */
165+
ret=-1;
166+
}
167+
}
168+
else
169+
{
170+
/* It's a junction point, so report it as a symlink. */
171+
buf->st_mode &= ~S_IFDIR;
172+
buf->st_mode |=S_IFLNK;
173+
buf->st_size=size;
174+
}
175+
}
176+
132177
CloseHandle(hFile);
133178
returnret;
134179
}
135180

181+
/*
182+
* Windows implementation of stat().
183+
*/
184+
int
185+
_pgstat64(constchar*name,structstat*buf)
186+
{
187+
intret;
188+
189+
ret=_pglstat64(name,buf);
190+
191+
/* Do we need to follow a symlink (junction point)? */
192+
if (ret==0&&S_ISLNK(buf->st_mode))
193+
{
194+
charnext[MAXPGPATH];
195+
ssize_tsize;
196+
197+
/*
198+
* _pglstat64() already called readlink() once to be able to fill in
199+
* st_size, and now we need to do it again to get the path to follow.
200+
* That could be optimized, but stat() on symlinks is probably rare
201+
* and this way is simple.
202+
*/
203+
size=readlink(name,next,sizeof(next));
204+
if (size<0)
205+
{
206+
if (errno==EACCES&&
207+
pg_RtlGetLastNtStatus()==STATUS_DELETE_PENDING)
208+
{
209+
/* Unlinked underneath us. */
210+
errno=ENOENT;
211+
}
212+
return-1;
213+
}
214+
if (size >=sizeof(next))
215+
{
216+
errno=ENAMETOOLONG;
217+
return-1;
218+
}
219+
next[size]=0;
220+
221+
ret=_pglstat64(next,buf);
222+
if (ret==0&&S_ISLNK(buf->st_mode))
223+
{
224+
/*
225+
* We're only prepared to go one hop, because we only expect to
226+
* deal with the simple cases that we create. The error for too
227+
* many symlinks is supposed to be ELOOP, but Windows hasn't got
228+
* it.
229+
*/
230+
errno=EIO;
231+
return-1;
232+
}
233+
}
234+
235+
returnret;
236+
}
237+
136238
/*
137239
* Windows implementation of fstat().
138240
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp