@ -297,6 +297,124 @@ pgsymlink(const char *oldpath, const char *newpath)
return 0 ;
}
/*
* pgreadlink - uses Win32 junction points
*/
int
pgreadlink ( const char * path , char * buf , size_t size )
{
DWORD attr ;
HANDLE h ;
char buffer [ MAX_PATH * sizeof ( WCHAR ) + sizeof ( REPARSE_JUNCTION_DATA_BUFFER ) ] ;
REPARSE_JUNCTION_DATA_BUFFER * reparseBuf = ( REPARSE_JUNCTION_DATA_BUFFER * ) buffer ;
DWORD len ;
int r ;
attr = GetFileAttributes ( path ) ;
if ( attr = = INVALID_FILE_ATTRIBUTES )
{
_dosmaperr ( GetLastError ( ) ) ;
return - 1 ;
}
if ( ( attr & FILE_ATTRIBUTE_REPARSE_POINT ) = = 0 )
{
errno = EINVAL ;
return - 1 ;
}
h = CreateFile ( path ,
GENERIC_READ ,
FILE_SHARE_READ | FILE_SHARE_WRITE ,
NULL ,
OPEN_EXISTING ,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS ,
0 ) ;
if ( h = = INVALID_HANDLE_VALUE )
{
_dosmaperr ( GetLastError ( ) ) ;
return - 1 ;
}
if ( ! DeviceIoControl ( h ,
FSCTL_GET_REPARSE_POINT ,
NULL ,
0 ,
( LPVOID ) reparseBuf ,
sizeof ( buffer ) ,
& len ,
NULL ) )
{
LPSTR msg ;
errno = 0 ;
FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM ,
NULL , GetLastError ( ) ,
MAKELANGID ( LANG_ENGLISH , SUBLANG_DEFAULT ) ,
( LPSTR ) & msg , 0 , NULL ) ;
# ifndef FRONTEND
ereport ( ERROR ,
( errcode_for_file_access ( ) ,
errmsg ( " could not get junction for \" %s \" : %s " ,
path , msg ) ) ) ;
# else
fprintf ( stderr , _ ( " could not get junction for \" %s \" : %s \n " ) ,
path , msg ) ;
# endif
LocalFree ( msg ) ;
CloseHandle ( h ) ;
errno = EINVAL ;
return - 1 ;
}
CloseHandle ( h ) ;
/* Got it, let's get some results from this */
if ( reparseBuf - > ReparseTag ! = IO_REPARSE_TAG_MOUNT_POINT )
{
errno = EINVAL ;
return - 1 ;
}
r = WideCharToMultiByte ( CP_ACP , 0 ,
reparseBuf - > PathBuffer , - 1 ,
buf ,
size ,
NULL , NULL ) ;
if ( r < = 0 )
{
errno = EINVAL ;
return - 1 ;
}
/*
* If the path starts with " \ ?? \" , which it will do in most (all?) cases,
* strip those out .
*/
if ( r > 4 & & strncmp ( buf , " \\ ?? \\ " , 4 ) = = 0 )
{
memmove ( buf , buf + 4 , strlen ( buf + 4 ) + 1 ) ;
r - = 4 ;
}
return r ;
}
/*
* Assumes the file exists , so will return false if it doesn ' t
* ( since a nonexistant file is not a junction )
*/
bool
pgwin32_is_junction ( char * path )
{
DWORD attr = GetFileAttributes ( path ) ;
if ( attr = = INVALID_FILE_ATTRIBUTES )
{
_dosmaperr ( GetLastError ( ) ) ;
return false ;
}
return ( ( attr & FILE_ATTRIBUTE_REPARSE_POINT ) = = FILE_ATTRIBUTE_REPARSE_POINT ) ;
}
# endif /* defined(WIN32) && !defined(__CYGWIN__) */