Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.47
diff -c -c -r1.47 port.h
*** src/include/port.h	1 Aug 2004 06:56:39 -0000	1.47
--- src/include/port.h	7 Aug 2004 21:36:14 -0000
***************
*** 80,86 ****
  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)
  #define EXE ".exe"
  #define DEVNULL "nul"
  #else
--- 80,86 ----
  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(WIN32) || defined(__CYGWIN__)
  #define EXE ".exe"
  #define DEVNULL "nul"
  #else
***************
*** 140,153 ****
  
  extern int pclose_check(FILE *stream);
  
! #if defined(__MINGW32__) || defined(__CYGWIN__)
  /*
!  * Win32 doesn't have reliable rename/unlink during concurrent access
   */
  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)
  #endif
  
  extern bool rmtree(char *path, bool rmtopdir);
--- 140,156 ----
  
  extern int pclose_check(FILE *stream);
  
! #if defined(WIN32) || defined(__CYGWIN__)
  /*
!  *	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);
! 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);
Index: src/port/dirmod.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/dirmod.c,v
retrieving revision 1.13
diff -c -c -r1.13 dirmod.c
*** src/port/dirmod.c	1 Aug 2004 06:19:26 -0000	1.13
--- src/port/dirmod.c	7 Aug 2004 21:36:19 -0000
***************
*** 33,42 ****
--- 33,46 ----
  
  
  #include "miscadmin.h"
+ #include <winioctl.h>
  
  #undef rename
  #undef unlink
  
+ /*
+  *	pgrename
+  */
  int
  pgrename(const char *from, const char *to)
  {
***************
*** 79,84 ****
--- 83,91 ----
  }
  
  
+ /*
+  *	pgunlink
+  */
  int
  pgunlink(const char *path)
  {
***************
*** 110,121 ****
  	return 0;
  }
  
  #endif
  
  #if defined(WIN32) || defined(__CYGWIN__)
! #define rmt_unlink(path) pgunlink(path)
! #else
! #define rmt_unlink(path) unlink(path)
  #endif
  
  #ifdef FRONTEND
--- 117,235 ----
  	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 unlink(path)	pgunlink(path)
  #endif
  
  #ifdef FRONTEND
***************
*** 175,190 ****
  	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
   *
   */
- 
  bool
  rmtree(char *path, bool rmtopdir)
  {
--- 289,303 ----
  	xfree(filenames);
  }
  
  /*
!  *	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,255 ****
  		}
  		else
  		{
! 			if (rmt_unlink(filepath) != 0)
  			{
  				rmt_cleanup(filenames);
  				return false;
--- 362,368 ----
  		}
  		else
  		{
! 			if (unlink(filepath) != 0)
  			{
  				rmt_cleanup(filenames);
  				return false;
