Win32 tablespace - Mailing list pgsql-patches

From Andreas Pflug
Subject Win32 tablespace
Date
Msg-id 411257EF.6090304@pse-consulting.de
Whole thread Raw
Responses Re: Win32 tablespace
Re: Win32 tablespace
List pgsql-patches
The attached patch implements a symlink for win32 using junctions, and
uses that for win32 tablespaces.

Regards,
Andreas
Index: tablespace.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/tablespace.c,v
retrieving revision 1.7
diff -u -r1.7 tablespace.c
--- tablespace.c    1 Aug 2004 20:30:48 -0000    1.7
+++ tablespace.c    5 Aug 2004 13:36:48 -0000
@@ -77,6 +77,113 @@
 static bool directory_is_empty(const char *path);


+
+#ifdef WIN32
+
+#define symlink pgsymlink
+#define HAVE_SYMLINK
+
+#include "winioctl.h"
+
+int pgsymlink(const char *oldpath, const char *newpath);
+
+
+/*
+ * 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)
+
+
+int
+pgsymlink(const char *oldpath, const char *newpath)
+{
+    HANDLE dirhandle;
+    DWORD len;
+
+    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);
+
+    char *p=nativeTarget;
+    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
+
+
 /*
  * Each database using a table space is isolated into its own name space
  * by a subdirectory named for the database OID.  On first creation of an
@@ -482,11 +589,19 @@
                  errmsg("could not unlink file \"%s\": %m",
                         subfile)));

+#ifdef WIN32
+        if (rmdir(location) < 0)
+        ereport(ERROR,
+                (errcode_for_file_access(),
+                 errmsg("could not remove junction dir \"%s\": %m",
+                        location)));
+#else
     if (unlink(location) < 0)
         ereport(ERROR,
                 (errcode_for_file_access(),
                  errmsg("could not unlink symbolic link \"%s\": %m",
                         location)));
+#endif

     pfree(subfile);
     pfree(location);

pgsql-patches by date:

Previous
From: Zhenbang Wei
Date:
Subject: pg_dump-zh_TW.po for current
Next
From: Tom Lane
Date:
Subject: Re: Epoch to timestamp conversion function patch