-import os, tempfile, heapq, binascii, traceback, array, stat
+import os, tempfile, heapq, binascii, traceback, array, stat, struct
from stat import S_IFREG, S_IFDIR
from time import time, strftime, localtime
noisy = True
use_foolscap_logging = True
+from allmydata.util.log import NOISY, OPERATIONAL, SCARY
+
if use_foolscap_logging:
- from allmydata.util.log import msg as logmsg, err as logerr, \
- NOISY, OPERATIONAL, SCARY, PrefixingLogMixin
+ from allmydata.util.log import msg as logmsg, err as logerr, PrefixingLogMixin
else:
def logmsg(s, level=None):
print s
def logerr(s, level=None):
print s
- NOISY = None
- OPERATIONAL = None
- SCARY = None
class PrefixingLogMixin:
def __init__(self, facility=None):
pass
return plaintext
def write(self, plaintext):
- if noisy: self.log(".write(%r)" % (plaintext,), level=NOISY)
+ if noisy: self.log(".write(<data of length %r>)" % (len(plaintext),), level=NOISY)
index = self.file.tell()
ciphertext = self._crypt(index, plaintext)
self.file.write(ciphertext)
p.resumeProducing()
def write(self, data):
- if noisy: self.log(".write(%r)" % (data,), level=NOISY)
+ if noisy: self.log(".write(<data of length %r>)" % (len(data),), level=NOISY)
if self.check_abort():
self.close()
return
def openShell(self, protocol):
self.log(".openShell(%r)" % (protocol,), level=OPERATIONAL)
- raise NotImplementedError
+ protocol.write("This server supports only SFTP, not shell sessions.\n")
+ protocol.processEnded(Reason(ProcessTerminated(exitCode=1)))
def execCommand(self, protocol, cmd):
self.log(".execCommand(%r, %r)" % (protocol, cmd), level=OPERATIONAL)
def extendedRequest(self, extendedName, extendedData):
self.log(".extendedRequest(%r, %r)" % (extendedName, extendedData), level=OPERATIONAL)
- # A client 'df' command requires the 'statvfs@openssh.com' extension,
- # but there's little point to implementing that since we would only
- # have faked values to report.
+ if extendedName == 'statvfs@openssh.com' or extendedName == 'fstatvfs@openssh.com':
+ # <http://dev.libssh.org/ticket/11>
+ return struct.pack('>QQQQQQQQQQQ',
+ 1024, # uint64 f_bsize /* file system block size */
+ 1024, # uint64 f_frsize /* fundamental fs block size */
+ 628318530, # uint64 f_blocks /* number of blocks (unit f_frsize) */
+ 314159265, # uint64 f_bfree /* free blocks in file system */
+ 314159265, # uint64 f_bavail /* free blocks for non-root */
+ 200000000, # uint64 f_files /* total file inodes */
+ 100000000, # uint64 f_ffree /* free file inodes */
+ 100000000, # uint64 f_favail /* free file inodes for non-root */
+ 0x1AF5, # uint64 f_fsid /* file system id */
+ 2, # uint64 f_flag /* bit mask = ST_NOSUID; not ST_RDONLY */
+ 65535, # uint64 f_namemax /* maximum filename length */
+ )
+
raise SFTPError(FX_OP_UNSUPPORTED, "extendedRequest %r" % extendedName)
def realPath(self, pathstring):
d.addCallback(lambda ign:
self.shouldFailWithSFTPError(sftp.FX_OP_UNSUPPORTED, "makeLink link file",
self.handler.makeLink, "link", "file"))
- d.addCallback(lambda ign:
- self.shouldFailWithSFTPError(sftp.FX_OP_UNSUPPORTED, "extendedRequest foo bar",
- self.handler.extendedRequest, "foo", "bar"))
return d
self.handler.makeDirectory, "small", {}))
return d
- def test_execCommand(self):
+ def test_execCommand_and_openShell(self):
class FakeProtocol:
def __init__(self):
self.output = ""
def processEnded(self, reason):
self.reason = reason
- protocol_ok = FakeProtocol()
+ protocol_df = FakeProtocol()
protocol_error = FakeProtocol()
+ protocol_shell = FakeProtocol()
- d = self._set_up("execCommand")
+ d = self._set_up("execCommand_and_openShell")
- d.addCallback(lambda ign: self.handler.execCommand(protocol_ok, "df -P -k /"))
- d.addCallback(lambda ign: self.failUnlessIn("1024-blocks", protocol_ok.output))
- d.addCallback(lambda ign: self.failUnless(isinstance(protocol_ok.reason.value, ProcessDone)))
+ d.addCallback(lambda ign: self.handler.execCommand(protocol_df, "df -P -k /"))
+ d.addCallback(lambda ign: self.failUnlessIn("1024-blocks", protocol_df.output))
+ d.addCallback(lambda ign: self.failUnless(isinstance(protocol_df.reason.value, ProcessDone)))
d.addCallback(lambda ign: self.handler.eofReceived())
d.addCallback(lambda ign: self.handler.closed())
d.addCallback(lambda ign: self.handler.execCommand(protocol_error, "error"))
- d.addCallback(lambda ign: self.failUnlessEqual(protocol_error.output, ""))
+ d.addCallback(lambda ign: self.failUnlessEqual("", protocol_error.output))
d.addCallback(lambda ign: self.failUnless(isinstance(protocol_error.reason.value, ProcessTerminated)))
d.addCallback(lambda ign: self.failUnlessEqual(protocol_error.reason.value.exitCode, 1))
+ d.addCallback(lambda ign: self.handler.closed())
+
+ d.addCallback(lambda ign: self.handler.openShell(protocol_shell))
+ d.addCallback(lambda ign: self.failUnlessIn("only SFTP", protocol_shell.output))
+ d.addCallback(lambda ign: self.failUnless(isinstance(protocol_shell.reason.value, ProcessTerminated)))
+ d.addCallback(lambda ign: self.failUnlessEqual(protocol_shell.reason.value.exitCode, 1))
+ d.addCallback(lambda ign: self.handler.closed())
+
+ return d
+
+ def test_extendedRequest(self):
+ d = self._set_up("extendedRequest")
+
+ d.addCallback(lambda ign: self.handler.extendedRequest("statvfs@openssh.com", "/"))
+ def _check(res):
+ self.failUnless(isinstance(res, str))
+ self.failUnlessEqual(len(res), 8*11)
+ d.addCallback(_check)
+
+ d.addCallback(lambda ign:
+ self.shouldFailWithSFTPError(sftp.FX_OP_UNSUPPORTED, "extendedRequest foo bar",
+ self.handler.extendedRequest, "foo", "bar"))
return d
\ No newline at end of file