2009-10-23 59 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