示例#1
0
def test_samefile_with_broken_symlink(smb_share):
    file1 = "%s\\file1.txt" % smb_share
    file2 = "%s\\file2.txt" % smb_share

    symlink(file1, file2)

    expected = "[NtStatus 0xc0000034] No such file or directory: "
    with pytest.raises(OSError, match=re.escape(expected)):
        samefile(file1, file2)
示例#2
0
def test_samefile_missing_path2(smb_share):
    file1 = "%s\\file1.txt" % smb_share
    file2 = "%s\\file2.txt" % smb_share

    with open_file(file2, mode='w') as fd:
        fd.write(u"content")

    expected = "[NtStatus 0xc0000034] No such file or directory: "
    with pytest.raises(OSError, match=re.escape(expected)):
        samefile(file1, file2)
示例#3
0
def test_samefile_with_symlink(smb_share):
    file1 = "%s\\file1.txt" % smb_share
    file2 = "%s\\file2.txt" % smb_share

    with open_file(file1, mode='w') as fd:
        fd.write(u"content")

    symlink(file1, file2)

    assert samefile(file1, file2) is True
示例#4
0
def test_samefile_with_different_files(smb_share):
    file1 = "%s\\file1.txt" % smb_share
    file2 = "%s\\file2.txt" % smb_share

    with open_file(file1, mode='w') as fd:
        fd.write(u"content")

    with open_file(file2, mode='w') as fd:
        fd.write(u"content")

    assert samefile(file1, file2) is False
def copyfile(src, dst, follow_symlinks=True, **kwargs):
    """
    Copy the contents (no metadata) of the file names src to a file named dst and return dst in the most efficient way
    possible. If the src and dst reside on the same UNC share then a more efficient remote side copy is used. If the
    src and dst reside on the same local path then the proper shutil.copyfile() method is called, otherwise the content
    is copied using copyfileobj() in chunks.

    dst must be the complete target file name; look at copy() for a copy that accepts a target directory path. If src
    dst specify the same file, ValueError is raised.

    The destination location must be writable; otherwise, an OSError exception will be raised. If dst already exists,
    it will be replaced. Special files such as character or block devices and pipes cannot be copied with this
    function.

    If follow_symlinks is 'False' and src is a symbolic link, a new symbolic link will be created instead of copying
    the file src points to. This will fail if the symbolic link at src is a different root as dst.

    :param src: The src filepath to copy.
    :param dst: The destinoation filepath to copy to.
    :param follow_symlinks: Whether to copy the symlink target of source or the symlink itself.
    :param kwargs: Common arguments used to build the SMB Session for any UNC paths.
    :return: The dst path.
    """
    def wrap_not_implemented(function_name):
        def raise_not_implemented(*args, **kwargs):
            raise NotImplementedError(
                "%s is unavailable on this platform as a local operation" %
                function_name)

        return raise_not_implemented

    norm_src = ntpath.normpath(src)
    if norm_src.startswith('\\\\'):
        src_root = ntpath.splitdrive(norm_src)[0]
        islink_func = islink
        readlink_func = readlink
        symlink_func = symlink
        src_open = open_file
        src_kwargs = kwargs
    else:
        src_root = None
        islink_func = os.path.islink
        # readlink and symlink are not available on Windows on Python 2.
        readlink_func = getattr(os, 'readlink',
                                wrap_not_implemented('readlink'))
        symlink_func = getattr(os, 'symlink', wrap_not_implemented('symlink'))
        src_open = open
        src_kwargs = {}

    norm_dst = ntpath.normpath(dst)
    if norm_dst.startswith('\\\\'):
        dst_root = ntpath.splitdrive(norm_dst)[0]
        dst_open = open_file
        dst_kwargs = kwargs
    else:
        dst_root = None
        dst_open = open
        dst_kwargs = {}

    if not follow_symlinks and islink_func(src, **src_kwargs):
        if src_root != dst_root:
            raise ValueError("Cannot copy a symlink on different roots.")

        symlink_func(readlink_func(src), dst, **src_kwargs)
        return dst

    if src_root is None and dst_root is None:
        # The files are local and follow_symlinks is True, rely on the builtin copyfile mechanism.
        shutil.copyfile(src, dst)
        return dst

    if src_root == dst_root:
        # The files are located on the same share and follow_symlinks is True, rely on smbclient.copyfile for an
        # efficient server side copy.
        try:
            is_same = samefile(src, dst, **kwargs)
        except OSError as err:
            if err.errno == errno.ENOENT:
                is_same = False
            else:
                raise

        if is_same:
            raise shutil.Error(
                to_native("'%s' and '%s' are the same file, cannot copy" %
                          (src, dst)))

        smbclient_copyfile(src, dst, **kwargs)
        return dst

    # Finally we are copying across different roots so we just chunk the data using copyfileobj
    with src_open(src, mode='rb',
                  **src_kwargs) as src_fd, dst_open(dst,
                                                    mode='wb',
                                                    **dst_kwargs) as dst_fd:
        copyfileobj(src_fd, dst_fd, MAX_PAYLOAD_SIZE)

    return dst