mirror of
https://github.com/boostorg/build.git
synced 2026-02-18 01:52:17 +00:00
Initial supprort for creating symlinks in the git layout.
[SVN r84524]
This commit is contained in:
@@ -29,6 +29,10 @@
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef OS_NT
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_EXECUNIX)
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
@@ -425,6 +429,11 @@ void load_builtins()
|
||||
char const * args [] = { "path", 0 };
|
||||
bind_builtin( "MAKEDIR", builtin_makedir, 0, args );
|
||||
}
|
||||
|
||||
{
|
||||
const char * args [] = { "path", 0 };
|
||||
bind_builtin( "READLINK", builtin_readlink, 0, args );
|
||||
}
|
||||
|
||||
/* Initialize builtin modules. */
|
||||
init_set();
|
||||
@@ -1827,6 +1836,94 @@ LIST * builtin_makedir( FRAME * frame, int flags )
|
||||
: list_new( object_copy( list_front( path ) ) );
|
||||
}
|
||||
|
||||
LIST *builtin_readlink( FRAME * frame, int flags )
|
||||
{
|
||||
const char * path = object_str( list_front( lol_get( frame->args, 0 ) ) );
|
||||
#ifdef OS_NT
|
||||
|
||||
/* This struct is declared in ntifs.h which is
|
||||
* part of the Windows Driver Kit.
|
||||
*/
|
||||
typedef struct _REPARSE_DATA_BUFFER {
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
USHORT Reserved;
|
||||
union {
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
ULONG Flags;
|
||||
WCHAR PathBuffer[ 1 ];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[ 1 ];
|
||||
} MountPointReparseBuffer;
|
||||
struct {
|
||||
UCHAR DataBuffer[ 1 ];
|
||||
} GenericReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER;
|
||||
|
||||
HANDLE hLink = CreateFileA( path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL );
|
||||
DWORD n;
|
||||
union {
|
||||
REPARSE_DATA_BUFFER reparse;
|
||||
char data[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
} buf;
|
||||
int okay = DeviceIoControl(hLink, FSCTL_GET_REPARSE_POINT, NULL, 0, &buf, sizeof(buf), &n, NULL);
|
||||
|
||||
CloseHandle( hLink );
|
||||
|
||||
if (okay && buf.reparse.ReparseTag == IO_REPARSE_TAG_SYMLINK )
|
||||
{
|
||||
int index = buf.reparse.SymbolicLinkReparseBuffer.SubstituteNameOffset / 2;
|
||||
int length = buf.reparse.SymbolicLinkReparseBuffer.SubstituteNameLength / 2;
|
||||
char cbuf[MAX_PATH + 1];
|
||||
int numchars = WideCharToMultiByte( CP_ACP, 0, buf.reparse.SymbolicLinkReparseBuffer.PathBuffer + index, length, cbuf, sizeof(cbuf), NULL, NULL );
|
||||
if( numchars >= sizeof(cbuf) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
cbuf[numchars] = '\0';
|
||||
return list_new( object_new( cbuf ) );
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
char static_buf[256];
|
||||
char * buf = static_buf;
|
||||
size_t bufsize = 256;
|
||||
LIST * result = 0;
|
||||
while (1) {
|
||||
ssize_t len = readlink( path, buf, bufsize );
|
||||
if ( len < 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if ( len < bufsize )
|
||||
{
|
||||
buf[ len ] = '\0';
|
||||
result = list_new( object_new( buf ) );
|
||||
break;
|
||||
}
|
||||
if ( buf != static_buf )
|
||||
BJAM_FREE( buf );
|
||||
bufsize *= 2;
|
||||
buf = BJAM_MALLOC( bufsize );
|
||||
}
|
||||
|
||||
if ( buf != static_buf )
|
||||
BJAM_FREE( buf );
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ LIST *builtin_pad( FRAME * frame, int flags );
|
||||
LIST *builtin_precious( FRAME * frame, int flags );
|
||||
LIST *builtin_self_path( FRAME * frame, int flags );
|
||||
LIST *builtin_makedir( FRAME * frame, int flags );
|
||||
LIST *builtin_readlink( FRAME * frame, int flags );
|
||||
|
||||
void backtrace( FRAME *frame );
|
||||
extern int last_update_now_status;
|
||||
|
||||
@@ -122,6 +122,19 @@ int file_collect_dir_content_( file_info_t * const d )
|
||||
ff->is_file = !ff->is_dir;
|
||||
ff->exists = 1;
|
||||
timestamp_from_filetime( &ff->time, &finfo.ftLastWriteTime );
|
||||
// Use the timestamp of the link target, not the link itself
|
||||
// (i.e. stat instead of lstat)
|
||||
if ( finfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
|
||||
{
|
||||
HANDLE hLink = CreateFileA( pathname->value, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
|
||||
BY_HANDLE_FILE_INFORMATION target_finfo[ 1 ];
|
||||
if ( hLink != INVALID_HANDLE_VALUE && GetFileInformationByHandle( hLink, target_finfo ) )
|
||||
{
|
||||
ff->is_file = target_finfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? 0 : 1;
|
||||
ff->is_dir = target_finfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? 1 : 0;
|
||||
timestamp_from_filetime( &ff->time, &target_finfo->ftLastWriteTime );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( FindNextFile( findHandle, &finfo ) );
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "object.h"
|
||||
|
||||
#ifdef OS_NT
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user