2009-10-23 62 views
2

在我努力解决Python issue 1578269时,我一直在努力尝试以稳健的方式解决符号链接的目标。我开始使用GetFinalPathNameByHandle作为建议here on stackoverflowMicrosoft,但事实证明,当目标正在使用时(例如使用pagefile.sys),技术会失败。Windows的这个符号链接遍历代码有问题吗?

所以,我写了一个新的例程来完成这个使用CreateFile和DeviceIoControl(因为它似乎这是什么浏览器)。下面包含了jaraco.windows.filesystem的相关代码。

问题是,是否有更好的技术来可靠地解析Windows中的符号链接?你能找出这个实现的任何问题吗?

def relpath(path, start=os.path.curdir): 
    """ 
    Like os.path.relpath, but actually honors the start path 
    if supplied. See http://bugs.python.org/issue7195 
    """ 
    return os.path.normpath(os.path.join(start, path)) 

def trace_symlink_target(link): 
    """ 
    Given a file that is known to be a symlink, trace it to its ultimate 
    target. 

    Raises TargetNotPresent when the target cannot be determined. 
    Raises ValueError when the specified link is not a symlink. 
    """ 

    if not is_symlink(link): 
    raise ValueError("link must point to a symlink on the system") 
    while is_symlink(link): 
    orig = os.path.dirname(link) 
    link = _trace_symlink_immediate_target(link) 
    link = relpath(link, orig) 
    return link 

def _trace_symlink_immediate_target(link): 
    handle = CreateFile(
    link, 
    0, 
    FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 
    None, 
    OPEN_EXISTING, 
    FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 
    None, 
    ) 

    res = DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 10240) 

    bytes = create_string_buffer(res) 
    p_rdb = cast(bytes, POINTER(REPARSE_DATA_BUFFER)) 
    rdb = p_rdb.contents 
    if not rdb.tag == IO_REPARSE_TAG_SYMLINK: 
    raise RuntimeError("Expected IO_REPARSE_TAG_SYMLINK, but got %d" % rdb.tag) 
    return rdb.get_print_name() 

回答

0

可惜我不能与Vista测试,直到下周,但GetFinalPathNameByHandle应该工作,即使是在使用的文件 - 什么是你注意到了这个问题? 在上面的代码中,忘记关闭文件句柄。

+0

这是我的失败。建立到pagefile.sys [cmd/c mklink pagefile2 pagefile.sys]的链接。然后尝试找到pagefile2的目标。要调用GetFinalPathNameByHandle(GFPNBH),您需要一个句柄。如果使用FILE_FLAG_OPEN_REPARSE_POINT,则GFPNBH将返回“pagefile2”。如果您尝试在没有该标志的情况下打开,CreateFile将返回一个错误“该进程无法访问该文件,因为该文件正在被另一个进程使用”。 – 2009-10-24 12:52:30