Content-Length: 493618 | pFad | http://github.com/postgrespro/postgres/commit/ba7bee837ec1cee4809cdbaeba2104be37dee5dc

A6 Backport "Add pgreadlink() on Windows to read junction points". · postgrespro/postgres@ba7bee8 · GitHub
Skip to content

Commit ba7bee8

Browse files
committed
Backport "Add pgreadlink() on Windows to read junction points".
The patch to recurseively fsync pgdata needs this, but it was only introduced in 9.1.
1 parent 262fbcb commit ba7bee8

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

src/include/port.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,11 @@ extern int pgunlink(const char *path);
291291
*/
292292
#if defined(WIN32) && !defined(__CYGWIN__)
293293
extern int pgsymlink(const char *oldpath, const char *newpath);
294+
extern int pgreadlink(const char *path, char *buf, size_t size);
295+
extern bool pgwin32_is_junction(char *path);
294296

295297
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
298+
#define readlink(path, buf, size) pgreadlink(path, buf, size)
296299
#endif
297300

298301
extern void copydir(char *fromdir, char *todir, bool recurse);

src/port/dirmod.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,124 @@ pgsymlink(const char *oldpath, const char *newpath)
297297

298298
return 0;
299299
}
300+
301+
/*
302+
* pgreadlink - uses Win32 junction points
303+
*/
304+
int
305+
pgreadlink(const char *path, char *buf, size_t size)
306+
{
307+
DWORD attr;
308+
HANDLE h;
309+
char buffer[MAX_PATH * sizeof(WCHAR) + sizeof(REPARSE_JUNCTION_DATA_BUFFER)];
310+
REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
311+
DWORD len;
312+
int r;
313+
314+
attr = GetFileAttributes(path);
315+
if (attr == INVALID_FILE_ATTRIBUTES)
316+
{
317+
_dosmaperr(GetLastError());
318+
return -1;
319+
}
320+
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
321+
{
322+
errno = EINVAL;
323+
return -1;
324+
}
325+
326+
h = CreateFile(path,
327+
GENERIC_READ,
328+
FILE_SHARE_READ | FILE_SHARE_WRITE,
329+
NULL,
330+
OPEN_EXISTING,
331+
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
332+
0);
333+
if (h == INVALID_HANDLE_VALUE)
334+
{
335+
_dosmaperr(GetLastError());
336+
return -1;
337+
}
338+
339+
if (!DeviceIoControl(h,
340+
FSCTL_GET_REPARSE_POINT,
341+
NULL,
342+
0,
343+
(LPVOID) reparseBuf,
344+
sizeof(buffer),
345+
&len,
346+
NULL))
347+
{
348+
LPSTR msg;
349+
350+
errno = 0;
351+
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
352+
NULL, GetLastError(),
353+
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
354+
(LPSTR) &msg, 0, NULL);
355+
#ifndef FRONTEND
356+
ereport(ERROR,
357+
(errcode_for_file_access(),
358+
errmsg("could not get junction for \"%s\": %s",
359+
path, msg)));
360+
#else
361+
fprintf(stderr, _("could not get junction for \"%s\": %s\n"),
362+
path, msg);
363+
#endif
364+
LocalFree(msg);
365+
CloseHandle(h);
366+
errno = EINVAL;
367+
return -1;
368+
}
369+
CloseHandle(h);
370+
371+
/* Got it, let's get some results from this */
372+
if (reparseBuf->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
373+
{
374+
errno = EINVAL;
375+
return -1;
376+
}
377+
378+
r = WideCharToMultiByte(CP_ACP, 0,
379+
reparseBuf->PathBuffer, -1,
380+
buf,
381+
size,
382+
NULL, NULL);
383+
384+
if (r <= 0)
385+
{
386+
errno = EINVAL;
387+
return -1;
388+
}
389+
390+
/*
391+
* If the path starts with "\??\", which it will do in most (all?) cases,
392+
* strip those out.
393+
*/
394+
if (r > 4 && strncmp(buf, "\\??\\", 4) == 0)
395+
{
396+
memmove(buf, buf + 4, strlen(buf + 4) + 1);
397+
r -= 4;
398+
}
399+
return r;
400+
}
401+
402+
/*
403+
* Assumes the file exists, so will return false if it doesn't
404+
* (since a nonexistant file is not a junction)
405+
*/
406+
bool
407+
pgwin32_is_junction(char *path)
408+
{
409+
DWORD attr = GetFileAttributes(path);
410+
411+
if (attr == INVALID_FILE_ATTRIBUTES)
412+
{
413+
_dosmaperr(GetLastError());
414+
return false;
415+
}
416+
return ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT);
417+
}
300418
#endif /* defined(WIN32) && !defined(__CYGWIN__) */
301419

302420

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgrespro/postgres/commit/ba7bee837ec1cee4809cdbaeba2104be37dee5dc

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy