diff --git a/src/engine/builtins.c b/src/engine/builtins.c index 3aa8e8122..e4626e30d 100644 --- a/src/engine/builtins.c +++ b/src/engine/builtins.c @@ -1893,6 +1893,28 @@ LIST *builtin_readlink( FRAME * frame, int flags ) cbuf[numchars] = '\0'; return list_new( object_new( cbuf ) ); } + else if( okay && buf.reparse.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT ) + { + int index = buf.reparse.MountPointReparseBuffer.SubstituteNameOffset / 2; + int length = buf.reparse.MountPointReparseBuffer.SubstituteNameLength / 2; + char cbuf[MAX_PATH + 1]; + const char * result; + int numchars = WideCharToMultiByte( CP_ACP, 0, buf.reparse.MountPointReparseBuffer.PathBuffer + index, length, cbuf, sizeof(cbuf), NULL, NULL ); + if( numchars >= sizeof(cbuf) ) + { + return 0; + } + cbuf[numchars] = '\0'; + /* strip off the leading "\??\" */ + result = cbuf; + if ( cbuf[ 0 ] == '\\' && cbuf[ 1 ] == '?' && + cbuf[ 2 ] == '?' && cbuf[ 3 ] == '\\' && + cbuf[ 4 ] != '\0' && cbuf[ 5 ] == ':' ) + { + result += 4; + } + return list_new( object_new( result ) ); + } return 0; #else char static_buf[256]; diff --git a/src/tools/link.jam b/src/tools/link.jam index 268fe10ab..4a7034b8a 100644 --- a/src/tools/link.jam +++ b/src/tools/link.jam @@ -60,6 +60,45 @@ rule can-symlink ( project : ps ) } } +if [ os.name ] = NT +{ + +# Test for Windows junctions (mklink /J) +rule can-junction ( project : ps ) +{ + if ! $(.can-junction) + { + local root-project = [ get-root-project $(project) ] ; + + local source-target = [ new file-target test-junction-source : : + $(project) : [ new action : common.mkdir ] ] ; + local target = [ new file-target test-junction : : + $(project) : [ new action $(source-target) : link.junction ] ] ; + + if [ configure.try-build $(target) : $(ps) : "junctions supported" ] + { + .can-junction = true ; + } + else + { + .can-junction = false ; + } + } + if $(.can-junction) = true + { + return true ; + } +} + +} +else +{ + +rule can-junction ( project : ps ) +{ +} + +} rule can-hardlink ( project : ps ) { @@ -149,8 +188,13 @@ class symlink-target-class : basic-target local files = [ path.glob-tree $(location) : * ] ; local targets ; - link.can-symlink $(self.project) : $(property-set) ; - link.can-hardlink $(self.project) : $(property-set) ; + # If we have symlinks, don't bother checking + # for hardlinks and junctions. + if ! [ link.can-symlink $(self.project) : $(property-set) ] + { + link.can-junction $(self.project) : $(property-set) ; + link.can-hardlink $(self.project) : $(property-set) ; + } if [ $(property-set).get ] { @@ -216,7 +260,18 @@ rule do-link } if [ os.name ] = NT { - MKLINK_OR_DIR on $(target) = mklink /D \"$(target)\" \"$(relative)\" ; + if $(.can-symlink) = true + { + MKLINK_OR_DIR on $(target) = mklink /D \"$(target)\" \"$(relative)\" ; + } + else + { + # This function should only be called + # if either symlinks or junctions are supported. + # To get here $(.can-junction) must be true. + mklink-opt = /J ; + MKLINK_OR_DIR on $(target) = mklink /J \"$(target)\" \"$(source)\" ; + } } else { @@ -329,7 +384,7 @@ rule link-recursively ( target : source : no-recurse ? ) split = true ; } } - else if $(.can-symlink) = false + else if $(.can-symlink) = false && $(.can-junction) = false { if [ READLINK [ path.native $(target) ] ] { @@ -384,6 +439,12 @@ rule mklink if [ os.name ] = NT { +actions junction +{ + if exist "$(<)" del "$(<)" + mklink /J "$(<)" "$(>)" +} + actions mklink { if exist "$(<)" del "$(<)"