OK, applied.  I moved the funciton into port/dirmod.c and cleaned up the
interface for Win32.

Would someone test this on Win32 in case I broke something?  Patch
attached.

---------------------------------------------------------------------------

Andreas Pflug wrote:
> The attached patch implements a symlink for win32 using junctions, and 
> uses that for win32 tablespaces.
> 
> Regards,
> Andreas


> 
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
>       subscribe-nomail command to [EMAIL PROTECTED] so that your
>       message can get through to the mailing list cleanly

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  [EMAIL PROTECTED]               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
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;
---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

Reply via email to