# # patch "paramiko/sftp_client.py" # from [e7da642c8bb505413bddce8b8d74b2cef3747a92] # to [5bd2a4fe7cfc525df863b12e4dd585afd4d34bb9] # # patch "paramiko/sftp_file.py" # from [5757e42b2f3cdffea10937e6c370663d8badda40] # to [b6da074f26d4d2e8f891d0eb823d8ac9e9d50121] # ======================================================================== --- paramiko/sftp_client.py e7da642c8bb505413bddce8b8d74b2cef3747a92 +++ paramiko/sftp_client.py 5bd2a4fe7cfc525df863b12e4dd585afd4d34bb9 @@ -185,7 +185,7 @@ if ('w' in mode): imode |= SFTP_FLAG_CREATE | SFTP_FLAG_TRUNC if ('a' in mode): - imode |= SFTP_FLAG_APPEND + imode |= SFTP_FLAG_APPEND | SFTP_FLAG_CREATE | SFTP_FLAG_WRITE attrblock = SFTPAttributes() t, msg = self._request(CMD_OPEN, filename, imode, attrblock) if t != CMD_HANDLE: ======================================================================== --- paramiko/sftp_file.py 5757e42b2f3cdffea10937e6c370663d8badda40 +++ paramiko/sftp_file.py b6da074f26d4d2e8f891d0eb823d8ac9e9d50121 @@ -45,6 +45,15 @@ self.close() def close(self): + # We allow double-close without signaling an error, because real + # Python file objects do. However, we must protect against actually + # sending multiple CMD_CLOSE packets, because after we close our + # handle, the same handle may be re-allocated by the server, and we + # may end up mysteriously closing some random other file. (This is + # especially important because we unconditionally call close() from + # __del__.) + if self._closed: + return BufferedFile.close(self) try: self.sftp._request(CMD_CLOSE, self.handle)