604
604
# raise the original with its traceback if we can.
607
def non_atomic_put(self, relpath, f, mode=None):
608
"""Copy the file-like object into the target location.
610
This function is not strictly safe to use. It is only meant to
611
be used when you already know that the target does not exist.
612
It is not safe, because it will open and truncate the remote
613
file. So there may be a time when the file has invalid contents.
615
:param relpath: The remote location to put the contents.
616
:param f: File-like object.
617
:param mode: Possible access permissions for new file.
618
None means do not set remote permissions.
620
abspath = self._remote_path(relpath)
621
path = self._sftp._adjust_cwd(abspath)
622
attr = SFTPAttributes()
625
omode = (SFTP_FLAG_WRITE | SFTP_FLAG_CREATE | SFTP_FLAG_TRUNC)
629
t, msg = self._sftp._request(CMD_OPEN, path, omode, attr)
631
raise TransportError('Expected an SFTP handle')
632
handle = msg.get_string()
633
fout = SFTPFile(self._sftp, handle, 'wb', -1)
634
except (paramiko.SSHException, IOError), e:
635
self._translate_io_exception(e, abspath, ': unable to open',
636
failure_exc=FileExists)
639
fout.set_pipelined(True)
641
except (IOError, paramiko.SSHException), e:
642
self._translate_io_exception(e, tmp_abspath)
643
# XXX: This doesn't truly help like we would like it to.
644
# The problem is that openssh strips sticky bits. So while we
645
# can properly set group write permission, we lose the group
646
# sticky bit. So it is probably best to stop chmodding, and
647
# just tell users that they need to set the umask correctly.
648
# The attr.st_mode = mode, will handle when the user wants the
649
# final mode to be more restrictive. And then we avoid a round
650
# trip. Unless paramiko decides to expose an async chmod()
652
# This is designed to chmod() right before we close.
653
# Because we set_pipelined() earlier, theoretically we might avoid
654
# The round trip for fout.close()
656
self._sftp.chmod(tmp_abspath, mode)
607
659
def iter_files_recursive(self):
608
660
"""Walk the relative paths of all files in this transport."""
609
661
queue = list(self.list_dir('.'))