难以实现readlink()函数

难以实现readlink()函数,第1张

难以实现readlink()函数

ERROR_MOD_NOT_FOUND
(126)可能是由于
windll.CloseHandle(hfile)
,它尝试加载“
closehandle.dll”。它不见了
kernel32

这是处理结点和符号链接的替代实现。

ctypes定义

import ctypesfrom ctypes import wintypeskernel32 = ctypes.WinDLL('kernel32', use_last_error=True)FILE_READ_ATTRIBUTES = 0x0080OPEN_EXISTING = 3FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000FILE_FLAG_BACKUP_SEMANTICS   = 0x02000000FILE_ATTRIBUTE_REPARSE_POINT = 0x0400IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003IO_REPARSE_TAG_SYMlink     = 0xA000000CFSCTL_GET_REPARSE_POINT    = 0x000900A8MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000LPDWORD = ctypes.POINTER(wintypes.DWORD)LPWIN32_FIND_DATA = ctypes.POINTER(wintypes.WIN32_FIND_DATAW)INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).valuedef IsReparseTagNameSurrogate(tag):    return bool(tag & 0x20000000)def _check_invalid_handle(result, func, args):    if result == INVALID_HANDLE_VALUE:        raise ctypes.WinError(ctypes.get_last_error())    return argsdef _check_bool(result, func, args):    if not result:        raise ctypes.WinError(ctypes.get_last_error())    return argskernel32.FindFirstFileW.errcheck = _check_invalid_handlekernel32.FindFirstFileW.restype = wintypes.HANDLEkernel32.FindFirstFileW.argtypes = (    wintypes.LPCWSTR,  # _In_  lpFileName    LPWIN32_FIND_DATA) # _Out_ lpFindFileDatakernel32.FindClose.argtypes = (    wintypes.HANDLE,) # _Inout_ hFindFilekernel32.CreateFileW.errcheck = _check_invalid_handlekernel32.CreateFileW.restype = wintypes.HANDLEkernel32.CreateFileW.argtypes = (    wintypes.LPCWSTR, # _In_     lpFileName    wintypes.DWORD,   # _In_     dwDesiredAccess    wintypes.DWORD,   # _In_     dwShareMode    wintypes.LPVOID,  # _In_opt_ lpSecurityAttributes    wintypes.DWORD,   # _In_     dwCreationDisposition    wintypes.DWORD,   # _In_     dwFlagsAndAttributes    wintypes.HANDLE)  # _In_opt_ hTemplateFilekernel32.CloseHandle.argtypes = (    wintypes.HANDLE,) # _In_ hObjectkernel32.DeviceIoControl.errcheck = _check_boolkernel32.DeviceIoControl.argtypes = (    wintypes.HANDLE,  # _In_        hDevice    wintypes.DWORD,   # _In_        dwIoControlCode    wintypes.LPVOID,  # _In_opt_    lpInBuffer    wintypes.DWORD,   # _In_        nInBufferSize    wintypes.LPVOID,  # _Out_opt_   lpOutBuffer    wintypes.DWORD,   # _In_        nOutBufferSize    LPDWORD,          # _Out_opt_   lpBytesReturned    wintypes.LPVOID)  # _Inout_opt_ lpOverlappedclass REPARSE_DATA_BUFFER(ctypes.Structure):    class ReparseData(ctypes.Union):        class linkData(ctypes.Structure): _fields_ = (('SubstituteNameOffset', wintypes.USHORT),  ('SubstituteNameLength', wintypes.USHORT),  ('PrintNameOffset',      wintypes.USHORT),  ('PrintNameLength',      wintypes.USHORT)) @property def PrintName(self):     dt = wintypes.WCHAR * (self.PrintNameLength //      ctypes.sizeof(wintypes.WCHAR))     name = dt.from_address(ctypes.addressof(self.PathBuffer) +      self.PrintNameOffset).value     if name.startswith(r'??'):         name = r'\?' + name[3:] # NT => Windows     return name        class SymboliclinkData(linkData): _fields_ = (('Flags',      wintypes.ULONG),  ('PathBuffer', wintypes.BYTE * 0))        class MountPointData(linkData): _fields_ = (('PathBuffer', wintypes.BYTE * 0),)        class GenericData(ctypes.Structure): _fields_ = (('DataBuffer', wintypes.BYTE * 0),)        _fields_ = (('SymboliclinkReparseBuffer', SymboliclinkData),         ('MountPointReparseBuffer',   MountPointData),         ('GenericReparseBuffer',      GenericData))    _fields_ = (('ReparseTag',        wintypes.ULONG),     ('ReparseDataLength', wintypes.USHORT),     ('Reserved',          wintypes.USHORT),     ('ReparseData',       ReparseData))    _anonymous_ = ('ReparseData',)

职能

def islink(path):    data = wintypes.WIN32_FIND_DATAW()    kernel32.FindClose(kernel32.FindFirstFileW(path, ctypes.byref(data)))    if not data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT:        return False    return IsReparseTagNameSurrogate(data.dwReserved0)def readlink(path):    n = wintypes.DWORd()    buf = (wintypes.BYTE * MAXIMUM_REPARSE_DATA_BUFFER_SIZE)()    flags = FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS    handle = kernel32.CreateFileW(path, FILE_READ_ATTRIBUTES, 0, None,     OPEN_EXISTING, flags, None)    try:        kernel32.DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 0, buf, ctypes.sizeof(buf), ctypes.byref(n), None)    finally:        kernel32.CloseHandle(handle)    rb = REPARSE_DATA_BUFFER.from_buffer(buf)    tag = rb.ReparseTag    if tag == IO_REPARSE_TAG_SYMlink:        return rb.SymboliclinkReparseBuffer.PrintName    if tag == IO_REPARSE_TAG_MOUNT_POINT:        return rb.MountPointReparseBuffer.PrintName    if not IsReparseTagNameSurrogate(tag):        raise ValueError("not a link")    raise ValueError("unsupported reparse tag: %d" % tag)

>>> sys.version'2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)]'>>> os.system(r'mklink /d spam C:Windows')symbolic link created for spam <<===>> C:Windows0>>> islink('spam')True>>> readlink('spam')u'C:\Windows'>>> islink('C:/documents and Settings') # junctionTrue>>> readlink('C:/documents and Settings')u'C:\Users'>>> islink('C:/Users/All Users') # symlinkdTrue>>> readlink('C:/Users/All Users')u'C:\ProgramData'


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5655056.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存