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);
---------------------------(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