mirror of
https://github.com/postgres/postgres.git
synced 2025-06-07 00:02:00 -04:00
The attached patch implements a symlink for win32 using junctions, and
uses that for win32 tablespaces. Andreas Pflug
This commit is contained in:
parent
27fedc8a5e
commit
53e8bec717
@ -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);
|
|||||||
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);
|
|||||||
|
|
||||||
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);
|
||||||
#define rename(from, to) pgrename(from, to)
|
extern int pgsymlink(const char *oldpath, const char *newpath);
|
||||||
#define unlink(path) pgunlink(path)
|
#define rename(from, to) pgrename(from, to)
|
||||||
|
#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 @@
|
|||||||
* 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 @@
|
|||||||
|
|
||||||
|
|
||||||
#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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pgunlink
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
pgunlink(const char *path)
|
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (rmt_unlink(filepath) != 0)
|
if (unlink(filepath) != 0)
|
||||||
{
|
{
|
||||||
rmt_cleanup(filenames);
|
rmt_cleanup(filenames);
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user