Commit 53e8bec7 authored by Bruce Momjian's avatar Bruce Momjian

The attached patch implements a symlink for win32 using junctions, and

uses that for win32 tablespaces.

Andreas Pflug
parent 27fedc8a
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/port.h,v 1.47 2004/08/01 06:56:39 momjian Exp $ * $PostgreSQL: pgsql/src/include/port.h,v 1.48 2004/08/07 21:48:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -80,7 +80,7 @@ extern void set_pglocale_pgservice(const char *argv0, const char *app); ...@@ -80,7 +80,7 @@ extern void set_pglocale_pgservice(const char *argv0, const char *app);
extern int find_my_exec(const char *argv0, char *retpath); extern int find_my_exec(const char *argv0, char *retpath);
extern int find_other_exec(const char *argv0, const char *target, extern int find_other_exec(const char *argv0, const char *target,
const char *versionstr, char *retpath); const char *versionstr, char *retpath);
#if defined(__CYGWIN__) || defined(WIN32) #if defined(WIN32) || defined(__CYGWIN__)
#define EXE ".exe" #define EXE ".exe"
#define DEVNULL "nul" #define DEVNULL "nul"
#else #else
...@@ -140,14 +140,17 @@ extern int pgkill(int pid, int sig); ...@@ -140,14 +140,17 @@ extern int pgkill(int pid, int sig);
extern int pclose_check(FILE *stream); extern int pclose_check(FILE *stream);
#if defined(__MINGW32__) || defined(__CYGWIN__) #if defined(WIN32) || defined(__CYGWIN__)
/* /*
* Win32 doesn't have reliable rename/unlink during concurrent access * Win32 doesn't have reliable rename/unlink during concurrent access,
* and we need special code to do symlinks.
*/ */
extern int pgrename(const char *from, const char *to); extern int pgrename(const char *from, const char *to);
extern int pgunlink(const char *path); extern int pgunlink(const char *path);
extern int pgsymlink(const char *oldpath, const char *newpath);
#define rename(from, to) pgrename(from, to) #define rename(from, to) pgrename(from, to)
#define unlink(path) pgunlink(path) #define unlink(path) pgunlink(path)
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
#endif #endif
extern bool rmtree(char *path, bool rmtopdir); extern bool rmtree(char *path, bool rmtopdir);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me. * Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.13 2004/08/01 06:19:26 momjian Exp $ * $PostgreSQL: pgsql/src/port/dirmod.c,v 1.14 2004/08/07 21:48:09 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,10 +33,14 @@ ...@@ -33,10 +33,14 @@
#include "miscadmin.h" #include "miscadmin.h"
#include <winioctl.h>
#undef rename #undef rename
#undef unlink #undef unlink
/*
* pgrename
*/
int int
pgrename(const char *from, const char *to) pgrename(const char *from, const char *to)
{ {
...@@ -79,6 +83,9 @@ pgrename(const char *from, const char *to) ...@@ -79,6 +83,9 @@ pgrename(const char *from, const char *to)
} }
/*
* pgunlink
*/
int int
pgunlink(const char *path) pgunlink(const char *path)
{ {
...@@ -110,12 +117,119 @@ pgunlink(const char *path) ...@@ -110,12 +117,119 @@ pgunlink(const char *path)
return 0; return 0;
} }
/*
* pgsymlink support:
*
* This struct is a replacement for REPARSE_DATA_BUFFER which is defined in VC6 winnt.h
* but omitted in later SDK functions.
* We only need the SymbolicLinkReparseBuffer part of the original struct's union.
*/
typedef struct
{
DWORD ReparseTag;
WORD ReparseDataLength;
WORD Reserved;
/* SymbolicLinkReparseBuffer */
WORD SubstituteNameOffset;
WORD SubstituteNameLength;
WORD PrintNameOffset;
WORD PrintNameLength;
WCHAR PathBuffer[1];
}
REPARSE_JUNCTION_DATA_BUFFER;
#define REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE \
FIELD_OFFSET(REPARSE_JUNCTION_DATA_BUFFER, SubstituteNameOffset)
/*
* pgsymlink - uses Win32 junction points
*
* For reference: http://www.codeproject.com/w2k/junctionpoints.asp
*/
int
pgsymlink(const char *oldpath, const char *newpath)
{
HANDLE dirhandle;
DWORD len;
char *p = nativeTarget;
char buffer[MAX_PATH*sizeof(WCHAR) + sizeof(REPARSE_JUNCTION_DATA_BUFFER)];
char nativeTarget[MAX_PATH];
REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER*)buffer;
CreateDirectory(newpath, 0);
dirhandle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
0, 0, OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
if (dirhandle == INVALID_HANDLE_VALUE)
return -1;
/* make sure we have an unparsed native win32 path */
if (memcmp("\\??\\", oldpath, 4))
sprintf(nativeTarget, "\\??\\%s", oldpath);
else
strcpy(nativeTarget, oldpath);
while ((p = strchr(p, '/')) != 0)
*p++ = '\\';
len = strlen(nativeTarget) * sizeof(WCHAR);
reparseBuf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
reparseBuf->ReparseDataLength = len + 12;
reparseBuf->Reserved = 0;
reparseBuf->SubstituteNameOffset = 0;
reparseBuf->SubstituteNameLength = len;
reparseBuf->PrintNameOffset = len+sizeof(WCHAR);
reparseBuf->PrintNameLength = 0;
MultiByteToWideChar(CP_ACP, 0, nativeTarget, -1,
reparseBuf->PathBuffer, MAX_PATH);
/*
* FSCTL_SET_REPARSE_POINT is coded differently depending on SDK version;
* we use our own definition
*/
if (!DeviceIoControl(dirhandle,
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS),
reparseBuf,
reparseBuf->ReparseDataLength + REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE,
0, 0, &len, 0))
{
LPSTR msg;
errno=0;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&msg, 0, NULL );
ereport(ERROR, (errcode_for_file_access(),
errmsg("Error setting junction for %s: %s", nativeTarget, msg)));
LocalFree(msg);
CloseHandle(dirhandle);
RemoveDirectory(newpath);
return -1;
}
CloseHandle(dirhandle);
return 0;
}
#endif #endif
/* ----------------
* rmtree routines
* ----------------
*/
/* We undefined these above, so we redefine them */
#if defined(WIN32) || defined(__CYGWIN__) #if defined(WIN32) || defined(__CYGWIN__)
#define rmt_unlink(path) pgunlink(path) #define unlink(path) pgunlink(path)
#else
#define rmt_unlink(path) unlink(path)
#endif #endif
#ifdef FRONTEND #ifdef FRONTEND
...@@ -175,16 +289,15 @@ rmt_cleanup(char ** filenames) ...@@ -175,16 +289,15 @@ rmt_cleanup(char ** filenames)
xfree(filenames); xfree(filenames);
} }
/* /*
* delete a directory tree recursively * rmtree
* assumes path points to a valid directory *
* deletes everything under path * Delete a directory tree recursively.
* if rmtopdir is true deletes the directory too * Assumes path points to a valid directory.
* Deletes everything under path.
* If rmtopdir is true deletes the directory too.
* *
*/ */
bool bool
rmtree(char *path, bool rmtopdir) rmtree(char *path, bool rmtopdir)
{ {
...@@ -249,7 +362,7 @@ rmtree(char *path, bool rmtopdir) ...@@ -249,7 +362,7 @@ rmtree(char *path, bool rmtopdir)
} }
else else
{ {
if (rmt_unlink(filepath) != 0) if (unlink(filepath) != 0)
{ {
rmt_cleanup(filenames); rmt_cleanup(filenames);
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment