38
38
except ImportError:
39
39
error('The SFTP transport requires paramiko.')
42
from paramiko.sftp import (SFTP_FLAG_WRITE, SFTP_FLAG_CREATE,
43
SFTP_FLAG_EXCL, SFTP_FLAG_TRUNC,
45
from paramiko.sftp_attr import SFTPAttributes
46
from paramiko.sftp_file import SFTPFile
43
49
SYSTEM_HOSTKEYS = {}
207
214
:param relpath: Location to put the contents, relative to base.
208
215
:param f: File-like or string object.
211
finalpath = self._abspath(relpath)
212
tmp_path = '%s.tmp.%.9f.%d.%d' % (finalpath, time.time(),
213
os.getpid(), random.randint(0,0x7FFFFFFF))
214
# I would *really* like to pass in the SFTP_FLAG_EXCL,
215
# but there doesn't seem to be a way to do it in the
216
# self._sftp.file() interface.
217
fout = self._sftp.file(tmp_path, 'wb')
219
# Maybe this should actually be using the relative form of tmp_path
220
self._translate_io_exception(e, relpath)
221
except (IOError, paramiko.SSHException), x:
222
raise SFTPTransportError('Unable to open file %r' % (tmp_path,), x)
217
finalpath = self._abspath(relpath)
218
tmp_path = '%s.tmp.%.9f.%d.%d' % (finalpath, time.time(),
219
os.getpid(), random.randint(0,0x7FFFFFFF))
220
fout = self._sftp_open_exclusive(tmp_path, relpath)
374
371
:return: A lock object, which should be passed to Transport.unlock()
376
# FIXME: there should be something clever i can do here...
373
# This is a little bit bogus, but basically, we create a file
374
# which should not already exist, and if it does, we assume
375
# that there is a lock, and if it doesn't, the we assume
376
# that we have taken the lock.
377
377
class BogusLock(object):
378
378
def __init__(self, path):
506
def _sftp_open_exclusive(self, path, relpath=None):
507
"""Open a remote path exclusively.
509
SFTP supports O_EXCL (SFTP_FLAG_EXCL), which fails if
510
the file already exists. However it does not expose this
511
at the higher level of SFTPClient.open(), so we have to
514
WARNING: This breaks the SFTPClient abstraction, so it
515
could easily break against an updated version of paramiko.
517
:param path: This should be an absolute remote path.
518
:param relpath: Just a parameter so we can throw better exceptions.
522
attr = SFTPAttributes()
523
mode = (SFTP_FLAG_WRITE | SFTP_FLAG_CREATE
524
| SFTP_FLAG_TRUNC | SFTP_FLAG_EXCL)
526
t, msg = self._sftp._request(CMD_OPEN, path, mode, attr)
528
raise SFTPTransportError('Expected an SFTP handle')
529
handle = msg.get_string()
530
return SFTPFile(self._sftp, handle, 'w', -1)
532
self._translate_io_exception(e, relpath)
533
except paramiko.SSHException, x:
534
raise SFTPTransportError('Unable to open file %r' % (path,), x)