Skip to content

Commit 53e8bec

Browse files
committed
The attached patch implements a symlink for win32 using junctions, and
uses that for win32 tablespaces. Andreas Pflug
1 parent 27fedc8 commit 53e8bec

File tree

2 files changed

+134
-18
lines changed

2 files changed

+134
-18
lines changed

src/include/port.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/port.h,v 1.47 2004/08/01 06:56:39 momjian Exp $
9+
* $PostgreSQL: pgsql/src/include/port.h,v 1.48 2004/08/07 21:48:09 momjian Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -80,7 +80,7 @@ extern void set_pglocale_pgservice(const char *argv0, const char *app);
8080
extern int find_my_exec(const char *argv0, char *retpath);
8181
extern int find_other_exec(const char *argv0, const char *target,
8282
const char *versionstr, char *retpath);
83-
#if defined(__CYGWIN__) || defined(WIN32)
83+
#if defined(WIN32) || defined(__CYGWIN__)
8484
#define EXE ".exe"
8585
#define DEVNULL "nul"
8686
#else
@@ -140,14 +140,17 @@ extern int pgkill(int pid, int sig);
140140

141141
extern int pclose_check(FILE *stream);
142142

143-
#if defined(__MINGW32__) || defined(__CYGWIN__)
143+
#if defined(WIN32) || defined(__CYGWIN__)
144144
/*
145-
* Win32 doesn't have reliable rename/unlink during concurrent access
145+
* Win32 doesn't have reliable rename/unlink during concurrent access,
146+
* and we need special code to do symlinks.
146147
*/
147148
extern int pgrename(const char *from, const char *to);
148149
extern int pgunlink(const char *path);
149-
#define rename(from, to) pgrename(from, to)
150-
#define unlink(path) pgunlink(path)
150+
extern int pgsymlink(const char *oldpath, const char *newpath);
151+
#define rename(from, to) pgrename(from, to)
152+
#define unlink(path) pgunlink(path)
153+
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
151154
#endif
152155

153156
extern bool rmtree(char *path, bool rmtopdir);

src/port/dirmod.c

Lines changed: 125 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.13 2004/08/01 06:19:26 momjian Exp $
13+
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.14 2004/08/07 21:48:09 momjian Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -33,10 +33,14 @@
3333

3434

3535
#include "miscadmin.h"
36+
#include <winioctl.h>
3637

3738
#undef rename
3839
#undef unlink
3940

41+
/*
42+
* pgrename
43+
*/
4044
int
4145
pgrename(const char *from, const char *to)
4246
{
@@ -79,6 +83,9 @@ pgrename(const char *from, const char *to)
7983
}
8084

8185

86+
/*
87+
* pgunlink
88+
*/
8289
int
8390
pgunlink(const char *path)
8491
{
@@ -110,12 +117,119 @@ pgunlink(const char *path)
110117
return 0;
111118
}
112119

120+
121+
/*
122+
* pgsymlink support:
123+
*
124+
* This struct is a replacement for REPARSE_DATA_BUFFER which is defined in VC6 winnt.h
125+
* but omitted in later SDK functions.
126+
* We only need the SymbolicLinkReparseBuffer part of the original struct's union.
127+
*/
128+
typedef struct
129+
{
130+
DWORD ReparseTag;
131+
WORD ReparseDataLength;
132+
WORD Reserved;
133+
/* SymbolicLinkReparseBuffer */
134+
WORD SubstituteNameOffset;
135+
WORD SubstituteNameLength;
136+
WORD PrintNameOffset;
137+
WORD PrintNameLength;
138+
WCHAR PathBuffer[1];
139+
}
140+
REPARSE_JUNCTION_DATA_BUFFER;
141+
142+
#define REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE \
143+
FIELD_OFFSET(REPARSE_JUNCTION_DATA_BUFFER, SubstituteNameOffset)
144+
145+
146+
/*
147+
* pgsymlink - uses Win32 junction points
148+
*
149+
* For reference: http://www.codeproject.com/w2k/junctionpoints.asp
150+
*/
151+
int
152+
pgsymlink(const char *oldpath, const char *newpath)
153+
{
154+
HANDLE dirhandle;
155+
DWORD len;
156+
char *p = nativeTarget;
157+
char buffer[MAX_PATH*sizeof(WCHAR) + sizeof(REPARSE_JUNCTION_DATA_BUFFER)];
158+
char nativeTarget[MAX_PATH];
159+
REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER*)buffer;
160+
161+
CreateDirectory(newpath, 0);
162+
dirhandle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
163+
0, 0, OPEN_EXISTING,
164+
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
165+
166+
if (dirhandle == INVALID_HANDLE_VALUE)
167+
return -1;
168+
169+
/* make sure we have an unparsed native win32 path */
170+
if (memcmp("\\??\\", oldpath, 4))
171+
sprintf(nativeTarget, "\\??\\%s", oldpath);
172+
else
173+
strcpy(nativeTarget, oldpath);
174+
175+
while ((p = strchr(p, '/')) != 0)
176+
*p++ = '\\';
177+
178+
len = strlen(nativeTarget) * sizeof(WCHAR);
179+
reparseBuf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
180+
reparseBuf->ReparseDataLength = len + 12;
181+
reparseBuf->Reserved = 0;
182+
reparseBuf->SubstituteNameOffset = 0;
183+
reparseBuf->SubstituteNameLength = len;
184+
reparseBuf->PrintNameOffset = len+sizeof(WCHAR);
185+
reparseBuf->PrintNameLength = 0;
186+
MultiByteToWideChar(CP_ACP, 0, nativeTarget, -1,
187+
reparseBuf->PathBuffer, MAX_PATH);
188+
189+
/*
190+
* FSCTL_SET_REPARSE_POINT is coded differently depending on SDK version;
191+
* we use our own definition
192+
*/
193+
if (!DeviceIoControl(dirhandle,
194+
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS),
195+
reparseBuf,
196+
reparseBuf->ReparseDataLength + REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE,
197+
0, 0, &len, 0))
198+
{
199+
LPSTR msg;
200+
201+
errno=0;
202+
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
203+
NULL, GetLastError(),
204+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
205+
(LPSTR)&msg, 0, NULL );
206+
ereport(ERROR, (errcode_for_file_access(),
207+
errmsg("Error setting junction for %s: %s", nativeTarget, msg)));
208+
209+
LocalFree(msg);
210+
211+
CloseHandle(dirhandle);
212+
RemoveDirectory(newpath);
213+
return -1;
214+
}
215+
216+
CloseHandle(dirhandle);
217+
218+
return 0;
219+
}
220+
113221
#endif
114222

223+
224+
/* ----------------
225+
* rmtree routines
226+
* ----------------
227+
*/
228+
229+
230+
/* We undefined these above, so we redefine them */
115231
#if defined(WIN32) || defined(__CYGWIN__)
116-
#define rmt_unlink(path) pgunlink(path)
117-
#else
118-
#define rmt_unlink(path) unlink(path)
232+
#define unlink(path) pgunlink(path)
119233
#endif
120234

121235
#ifdef FRONTEND
@@ -175,16 +289,15 @@ rmt_cleanup(char ** filenames)
175289
xfree(filenames);
176290
}
177291

178-
179-
180292
/*
181-
* delete a directory tree recursively
182-
* assumes path points to a valid directory
183-
* deletes everything under path
184-
* if rmtopdir is true deletes the directory too
293+
* rmtree
294+
*
295+
* Delete a directory tree recursively.
296+
* Assumes path points to a valid directory.
297+
* Deletes everything under path.
298+
* If rmtopdir is true deletes the directory too.
185299
*
186300
*/
187-
188301
bool
189302
rmtree(char *path, bool rmtopdir)
190303
{
@@ -249,7 +362,7 @@ rmtree(char *path, bool rmtopdir)
249362
}
250363
else
251364
{
252-
if (rmt_unlink(filepath) != 0)
365+
if (unlink(filepath) != 0)
253366
{
254367
rmt_cleanup(filenames);
255368
return false;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy