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: