提交 53e8bec7 编写于 作者: B Bruce Momjian

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

uses that for win32 tablespaces.

Andreas Pflug
上级 27fedc8a
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* 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);
extern int find_my_exec(const char *argv0, char *retpath);
extern int find_other_exec(const char *argv0, const char *target,
const char *versionstr, char *retpath);
#if defined(__CYGWIN__) || defined(WIN32)
#if defined(WIN32) || defined(__CYGWIN__)
#define EXE ".exe"
#define DEVNULL "nul"
#else
......@@ -140,14 +140,17 @@ extern int pgkill(int pid, int sig);
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 pgunlink(const char *path);
#define rename(from, to) pgrename(from, to)
#define unlink(path) pgunlink(path)
extern int pgsymlink(const char *oldpath, const char *newpath);
#define rename(from, to) pgrename(from, to)
#define unlink(path) pgunlink(path)
#define symlink(oldpath, newpath) pgsymlink(oldpath, newpath)
#endif
extern bool rmtree(char *path, bool rmtopdir);
......
......@@ -10,7 +10,7 @@
* Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me.
*
* 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 @@
#include "miscadmin.h"
#include <winioctl.h>
#undef rename
#undef unlink
/*
* pgrename
*/
int
pgrename(const char *from, const char *to)
{
......@@ -79,6 +83,9 @@ pgrename(const char *from, const char *to)
}
/*
* pgunlink
*/
int
pgunlink(const char *path)
{
......@@ -110,12 +117,119 @@ pgunlink(const char *path)
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
/* ----------------
* rmtree routines
* ----------------
*/
/* We undefined these above, so we redefine them */
#if defined(WIN32) || defined(__CYGWIN__)
#define rmt_unlink(path) pgunlink(path)
#else
#define rmt_unlink(path) unlink(path)
#define unlink(path) pgunlink(path)
#endif
#ifdef FRONTEND
......@@ -175,16 +289,15 @@ rmt_cleanup(char ** filenames)
xfree(filenames);
}
/*
* delete a directory tree recursively
* assumes path points to a valid directory
* deletes everything under path
* if rmtopdir is true deletes the directory too
* rmtree
*
* Delete a directory tree recursively.
* Assumes path points to a valid directory.
* Deletes everything under path.
* If rmtopdir is true deletes the directory too.
*
*/
bool
rmtree(char *path, bool rmtopdir)
{
......@@ -249,7 +362,7 @@ rmtree(char *path, bool rmtopdir)
}
else
{
if (rmt_unlink(filepath) != 0)
if (unlink(filepath) != 0)
{
rmt_cleanup(filenames);
return false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册