~bzr-pqm/bzr/bzr.dev

1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
1
# Copyright (C) 2005 Robey Pointer <robey@lag.net>, Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
16
17
"""
18
A stub SFTP server for loopback SFTP testing.
19
Adapted from the one in paramiko's unit tests.
20
"""
21
22
import os
23
from paramiko import ServerInterface, SFTPServerInterface, SFTPServer, SFTPAttributes, \
24
    SFTPHandle, SFTP_OK, AUTH_SUCCESSFUL, OPEN_SUCCEEDED
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
25
import sys
1666.1.6 by Robert Collins
Make knit the default format.
26
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
27
from bzrlib.osutils import pathjoin
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
28
from bzrlib.trace import mutter
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
29
30
31
class StubServer (ServerInterface):
1666.1.6 by Robert Collins
Make knit the default format.
32
1185.49.10 by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp).
33
    def __init__(self, test_case):
34
        ServerInterface.__init__(self)
35
        self._test_case = test_case
36
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
37
    def check_auth_password(self, username, password):
38
        # all are allowed
1185.49.10 by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp).
39
        self._test_case.log('sftpserver - authorizing: %s' % (username,))
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
40
        return AUTH_SUCCESSFUL
41
42
    def check_channel_request(self, kind, chanid):
1185.49.10 by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp).
43
        self._test_case.log('sftpserver - channel request: %s, %s' % (kind, chanid))
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
44
        return OPEN_SUCCEEDED
45
46
47
class StubSFTPHandle (SFTPHandle):
48
    def stat(self):
49
        try:
50
            return SFTPAttributes.from_stat(os.fstat(self.readfile.fileno()))
51
        except OSError, e:
52
            return SFTPServer.convert_errno(e.errno)
53
54
    def chattr(self, attr):
55
        # python doesn't have equivalents to fchown or fchmod, so we have to
56
        # use the stored filename
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
57
        mutter('Changing permissions on %s to %s', self.filename, attr)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
58
        try:
59
            SFTPServer.set_file_attr(self.filename, attr)
60
        except OSError, e:
61
            return SFTPServer.convert_errno(e.errno)
62
63
64
class StubSFTPServer (SFTPServerInterface):
1666.1.6 by Robert Collins
Make knit the default format.
65
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
66
    def __init__(self, server, root, home=None):
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
67
        SFTPServerInterface.__init__(self, server)
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
68
        # All paths are actually relative to 'root'.
69
        # this is like implementing chroot().
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
70
        self.root = root
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
71
        if home is None:
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
72
            self.home = ''
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
73
        else:
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
74
            if not home.startswith(self.root):
75
                raise AssertionError(
76
                    "home must be a subdirectory of root (%s vs %s)"
77
                    % (home, root))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
78
            self.home = home[len(self.root):]
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
79
        if self.home.startswith('/'):
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
80
            self.home = self.home[1:]
1547.1.1 by Robey Pointer
modify the sftp unit tests to perform sftp over a direct localhost socket instead of over an actual ssh2 transport
81
        server._test_case.log('sftpserver - new connection')
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
82
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
83
    def _realpath(self, path):
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
84
        # paths returned from self.canonicalize() always start with
85
        # a path separator. So if 'root' is just '/', this would cause
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
86
        # a double slash at the beginning '//home/dir'.
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
87
        if self.root == '/':
88
            return self.canonicalize(path)
89
        return self.root + self.canonicalize(path)
90
91
    if sys.platform == 'win32':
92
        def canonicalize(self, path):
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
93
            # Win32 sftp paths end up looking like
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
94
            #     sftp://host@foo/h:/foo/bar
95
            # which means absolute paths look like:
96
            #     /h:/foo/bar
97
            # and relative paths stay the same:
98
            #     foo/bar
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
99
            # win32 needs to use the Unicode APIs. so we require the
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
100
            # paths to be utf8 (Linux just uses bytestreams)
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
101
            thispath = path.decode('utf8')
102
            if path.startswith('/'):
1711.5.4 by John Arbash Meinel
Update stub_sftp based on Robey's comments.
103
                # Abspath H:/foo/bar
104
                return os.path.normpath(thispath[1:])
105
            else:
106
                return os.path.normpath(os.path.join(self.home, thispath))
107
    else:
108
        def canonicalize(self, path):
109
            if os.path.isabs(path):
110
                return os.path.normpath(path)
111
            else:
112
                return os.path.normpath('/' + os.path.join(self.home, path))
1524.1.1 by Robert Collins
Test sftp with relative, absolute-in-homedir and absolute-not-in-homedir
113
1185.58.2 by John Arbash Meinel
Added mode to the appropriate transport functions, and tests to make sure they work.
114
    def chattr(self, path, attr):
115
        try:
116
            SFTPServer.set_file_attr(path, attr)
117
        except OSError, e:
118
            return SFTPServer.convert_errno(e.errno)
119
        return SFTP_OK
120
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
121
    def list_folder(self, path):
122
        path = self._realpath(path)
123
        try:
124
            out = [ ]
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
125
            # TODO: win32 incorrectly lists paths with non-ascii if path is not
126
            # unicode. However on Linux the server should only deal with
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
127
            # bytestreams and posix.listdir does the right thing
1711.5.1 by John Arbash Meinel
Get most SFTP tests to pass. StubSFTPServer now talks the same path protocol that SFTPTransport talks. on win32
128
            if sys.platform == 'win32':
129
                flist = [f.encode('utf8') for f in os.listdir(path)]
130
            else:
131
                flist = os.listdir(path)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
132
            for fname in flist:
1185.31.32 by John Arbash Meinel
Updated the bzr sourcecode to use bzrlib.osutils.pathjoin rather than os.path.join to enforce internal use of / instead of \
133
                attr = SFTPAttributes.from_stat(os.stat(pathjoin(path, fname)))
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
134
                attr.filename = fname
135
                out.append(attr)
136
            return out
137
        except OSError, e:
138
            return SFTPServer.convert_errno(e.errno)
139
140
    def stat(self, path):
141
        path = self._realpath(path)
142
        try:
143
            return SFTPAttributes.from_stat(os.stat(path))
144
        except OSError, e:
145
            return SFTPServer.convert_errno(e.errno)
146
147
    def lstat(self, path):
148
        path = self._realpath(path)
149
        try:
150
            return SFTPAttributes.from_stat(os.lstat(path))
151
        except OSError, e:
152
            return SFTPServer.convert_errno(e.errno)
153
154
    def open(self, path, flags, attr):
155
        path = self._realpath(path)
156
        try:
1963.2.4 by Robey Pointer
remove usage of hasattr
157
            flags |= getattr(os, 'O_BINARY', 0)
1540.1.9 by John Arbash Meinel
Cleanup getattr() code, since getattr(None, '', None) still works
158
            if getattr(attr, 'st_mode', None):
1185.58.10 by John Arbash Meinel
[patch] Robey Pointer to fix sftp server using umask for files (failing tests for directories)
159
                fd = os.open(path, flags, attr.st_mode)
160
            else:
1988.1.1 by John Arbash Meinel
Restore mode bit tests for sftp, and track down bugs
161
                # os.open() defaults to 0777 which is
162
                # an odd default mode for files
163
                fd = os.open(path, flags, 0666)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
164
        except OSError, e:
165
            return SFTPServer.convert_errno(e.errno)
1685.1.72 by Wouter van Heyst
StubSFTPServer should use bytestreams rather than unicode
166
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
167
        if (flags & os.O_CREAT) and (attr is not None):
1185.58.10 by John Arbash Meinel
[patch] Robey Pointer to fix sftp server using umask for files (failing tests for directories)
168
            attr._flags &= ~attr.FLAG_PERMISSIONS
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
169
            SFTPServer.set_file_attr(path, attr)
170
        if flags & os.O_WRONLY:
1185.31.51 by John Arbash Meinel
Setting binary flags for sftp.
171
            fstr = 'wb'
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
172
        elif flags & os.O_RDWR:
1185.31.51 by John Arbash Meinel
Setting binary flags for sftp.
173
            fstr = 'rb+'
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
174
        else:
175
            # O_RDONLY (== 0)
1185.31.51 by John Arbash Meinel
Setting binary flags for sftp.
176
            fstr = 'rb'
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
177
        try:
178
            f = os.fdopen(fd, fstr)
1711.3.1 by John Arbash Meinel
opening a dir instead of a file raises an IOError, not OSError
179
        except (IOError, OSError), e:
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
180
            return SFTPServer.convert_errno(e.errno)
181
        fobj = StubSFTPHandle()
182
        fobj.filename = path
183
        fobj.readfile = f
184
        fobj.writefile = f
185
        return fobj
186
187
    def remove(self, path):
188
        path = self._realpath(path)
189
        try:
190
            os.remove(path)
191
        except OSError, e:
192
            return SFTPServer.convert_errno(e.errno)
193
        return SFTP_OK
194
195
    def rename(self, oldpath, newpath):
196
        oldpath = self._realpath(oldpath)
197
        newpath = self._realpath(newpath)
198
        try:
199
            os.rename(oldpath, newpath)
200
        except OSError, e:
201
            return SFTPServer.convert_errno(e.errno)
202
        return SFTP_OK
203
204
    def mkdir(self, path, attr):
205
        path = self._realpath(path)
206
        try:
1540.1.5 by John Arbash Meinel
Bugfix to allow using paramiko > 1.5.2
207
            # Using getattr() in case st_mode is None or 0
208
            # both evaluate to False
1540.1.9 by John Arbash Meinel
Cleanup getattr() code, since getattr(None, '', None) still works
209
            if getattr(attr, 'st_mode', None):
1185.58.11 by John Arbash Meinel
Made the StubSFTPServer use umask even for mkdir()
210
                os.mkdir(path, attr.st_mode)
211
            else:
212
                os.mkdir(path)
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
213
            if attr is not None:
1185.58.11 by John Arbash Meinel
Made the StubSFTPServer use umask even for mkdir()
214
                attr._flags &= ~attr.FLAG_PERMISSIONS
1185.16.127 by Martin Pool
[patch] paramiko sftp tests (robey)
215
                SFTPServer.set_file_attr(path, attr)
216
        except OSError, e:
217
            return SFTPServer.convert_errno(e.errno)
218
        return SFTP_OK
219
220
    def rmdir(self, path):
221
        path = self._realpath(path)
222
        try:
223
            os.rmdir(path)
224
        except OSError, e:
225
            return SFTPServer.convert_errno(e.errno)
226
        return SFTP_OK
227
228
    # removed: chattr, symlink, readlink
229
    # (nothing in bzr's sftp transport uses those)