Example #1
0
def readlink(link):
    """
	readlink(link) -> target
	Return a string representing the path to which the symbolic link points.
	"""
    handle = api.CreateFile(
        link,
        0,
        0,
        None,
        api.OPEN_EXISTING,
        api.FILE_FLAG_OPEN_REPARSE_POINT | api.FILE_FLAG_BACKUP_SEMANTICS,
        None,
    )

    if handle == api.INVALID_HANDLE_VALUE:
        raise WindowsError()

    res = reparse.DeviceIoControl(handle, api.FSCTL_GET_REPARSE_POINT, None,
                                  10240)

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

    handle_nonzero_success(api.CloseHandle(handle))
    return rdb.get_substitute_name()
Example #2
0
def get_file_info(path):
    # open the file the same way CPython does in posixmodule.c
    desired_access = api.FILE_READ_ATTRIBUTES
    share_mode = 0
    security_attributes = None
    creation_disposition = api.OPEN_EXISTING
    flags_and_attributes = (api.FILE_ATTRIBUTE_NORMAL
                            | api.FILE_FLAG_BACKUP_SEMANTICS
                            | api.FILE_FLAG_OPEN_REPARSE_POINT)
    template_file = None

    handle = api.CreateFile(
        path,
        desired_access,
        share_mode,
        security_attributes,
        creation_disposition,
        flags_and_attributes,
        template_file,
    )

    if handle == api.INVALID_HANDLE_VALUE:
        raise WindowsError()

    info = api.BY_HANDLE_FILE_INFORMATION()
    res = api.GetFileInformationByHandle(handle, info)
    handle_nonzero_success(res)
    handle_nonzero_success(api.CloseHandle(handle))

    return info
Example #3
0
def get_symlink_target(link):
    """
    get_symlink_target(link) -> target
    Return a string representing the path to which the symbolic link points.
    Similar to jaraco.windows.filesystem.readlink(link) except that 
    opened file handle is closed properly, to prevent leak
    """
    import jaraco.windows.api.filesystem as api
    import jaraco.windows.error as e
    from ctypes import (POINTER, cast, create_string_buffer)
    handle = api.CreateFile(
        link,
        0,
        0,
        None,
        api.OPEN_EXISTING,
        api.FILE_FLAG_OPEN_REPARSE_POINT | api.FILE_FLAG_BACKUP_SEMANTICS,
        None,
    )

    if handle == api.INVALID_HANDLE_VALUE:
        raise WindowsError()

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

    bytes = create_string_buffer(res)
    p_rdb = cast(bytes, POINTER(api.REPARSE_DATA_BUFFER))
    rdb = p_rdb.contents
    e.handle_nonzero_success(api.CloseHandle(handle))
    if not rdb.tag == api.IO_REPARSE_TAG_SYMLINK:
        raise RuntimeError("Expected IO_REPARSE_TAG_SYMLINK, but got %d" %
                           rdb.tag)
    return rdb.get_print_name()
Example #4
0
def get_final_path(path):
    r"""
	For a given path, determine the ultimate location of that path.
	Useful for resolving symlink targets.
	This functions wraps the GetFinalPathNameByHandle from the Windows
	SDK.

	Note, this function fails if a handle cannot be obtained (such as
	for C:\Pagefile.sys on a stock windows system). Consider using
	trace_symlink_target instead.
	"""
    desired_access = api.NULL
    share_mode = (api.FILE_SHARE_READ | api.FILE_SHARE_WRITE
                  | api.FILE_SHARE_DELETE)
    security_attributes = api.LPSECURITY_ATTRIBUTES()  # NULL pointer
    hFile = api.CreateFile(
        path,
        desired_access,
        share_mode,
        security_attributes,
        api.OPEN_EXISTING,
        api.FILE_FLAG_BACKUP_SEMANTICS,
        api.NULL,
    )

    if hFile == api.INVALID_HANDLE_VALUE:
        raise WindowsError()

    buf_size = api.GetFinalPathNameByHandle(hFile, LPWSTR(), 0,
                                            api.VOLUME_NAME_DOS)
    handle_nonzero_success(buf_size)
    buf = create_unicode_buffer(buf_size)
    result_length = api.GetFinalPathNameByHandle(hFile, buf, len(buf),
                                                 api.VOLUME_NAME_DOS)

    assert result_length < len(buf)
    handle_nonzero_success(result_length)
    handle_nonzero_success(api.CloseHandle(hFile))

    return buf[:result_length]