Create NTFS junction point in Python

后端 未结 5 1319
一整个雨季
一整个雨季 2020-12-05 11:02

Is there a way to create an NTFS junction point in Python? I know I can call the junction utility, but it would be better not to rely on external tools.

5条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-05 11:28

    Based on the accepted answer by Charles, here improved (and cross-platform) versions of the functions (Python 2.7 and 3.5+).

    • islink() now also detects file symbolic links under Windows (just like the POSIX equivalent)
    • parse_reparse_buffer() and readlink() now actually detect the type of reparse point (NTFS Junction, symlink or generic) which is needed to correctly decode the path
    • readlink() no longer fails with access denied on NTFS Junctions or directory symlinks (unless you really have no permission to read attributes)

    import os
    import struct
    import sys
    
    if sys.platform == "win32":
        from win32file import *
        from winioctlcon import FSCTL_GET_REPARSE_POINT
    
    __all__ = ['islink', 'readlink']
    
    # Win32file doesn't seem to have this attribute.
    FILE_ATTRIBUTE_REPARSE_POINT = 1024
    
    # These are defined in win32\lib\winnt.py, but with wrong values
    IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003  # Junction
    IO_REPARSE_TAG_SYMLINK = 0xA000000C
    
    def islink(path):
        """
        Cross-platform islink implementation.
    
        Supports Windows NT symbolic links and reparse points.
    
        """
        if sys.platform != "win32" or sys.getwindowsversion()[0] < 6:
            return os.path.islink(path)
        return bool(os.path.exists(path) and GetFileAttributes(path) &
                    FILE_ATTRIBUTE_REPARSE_POINT == FILE_ATTRIBUTE_REPARSE_POINT)
    
    
    def parse_reparse_buffer(buf):
        """ Implementing the below in Python:
    
        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;
            } DUMMYUNIONNAME;
        } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
    
        """
        # See https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/ns-ntifs-_reparse_data_buffer
    
        data = {'tag': struct.unpack(' 4 and rpath[0:4] == '\\??\\':
            rpath = rpath[4:]
        return rpath
    

提交回复
热议问题