Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

136 lines (112 sloc) 4.37 kb
/*
* Source: http://www.mail-archive.com/pgsql-committers@postgresql.org/msg03912.html
* Portions Copyright (c) 1996-2004, The PostgreSQL Global Development Group
* $PostgreSQL: pgsql-server/src/port/dirmod.c,v 1.13 2004/08/01 06:19:26 momjian Exp $
*/
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2004, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this
paragraph and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
/*
* 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 nativeTarget[MAX_PATH];
char *p = nativeTarget;
char buffer[MAX_PATH*sizeof(WCHAR) + sizeof(REPARSE_JUNCTION_DATA_BUFFER)];
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 = (unsigned short)(len + 12);
reparseBuf->Reserved = 0;
reparseBuf->SubstituteNameOffset = 0;
reparseBuf->SubstituteNameLength = (unsigned short)(len);
reparseBuf->PrintNameOffset = (unsigned short)(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 );
Perl_warn(aTHX_ "Error setting junction for %s: %s", nativeTarget, msg);
LocalFree(msg);
CloseHandle(dirhandle);
RemoveDirectory(newpath);
return -1;
}
CloseHandle(dirhandle);
return 0;
}
Jump to Line
Something went wrong with that request. Please try again.