From 5d49f4e629f510ff8e5a169c5c0189eb603fca34 Mon Sep 17 00:00:00 2001 From: Pascal Grange Date: Mon, 15 Feb 2016 10:18:44 +0100 Subject: [PATCH] Fix related to #13981 When working around "bad systems that insist on not allowing updates in an atomic manner", we should not run previous exception management code that tries to perform atomic move in case of exception since the dirty non atomic move has already been performed. --- lib/ansible/module_utils/basic.py | 62 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 3c14af7fbb..8d87511ae4 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -1758,39 +1758,39 @@ class AnsibleModule(object): # only try workarounds for errno 18 (cross device), 1 (not permitted), 13 (permission denied) # and 26 (text file busy) which happens on vagrant synced folders and other 'exotic' non posix file systems self.fail_json(msg='Could not replace file: %s to %s: %s' % (src, dest, e)) - - dest_dir = os.path.dirname(dest) - dest_file = os.path.basename(dest) - try: - tmp_dest = tempfile.NamedTemporaryFile( - prefix=".ansible_tmp", dir=dest_dir, suffix=dest_file) - except (OSError, IOError): - e = get_exception() - self.fail_json(msg='The destination directory (%s) is not writable by the current user.' % dest_dir) - - try: # leaves tmp file behind when sudo and not root - if switched_user and os.getuid() != 0: - # cleanup will happen by 'rm' of tempdir - # copy2 will preserve some metadata - shutil.copy2(src, tmp_dest.name) - else: - shutil.move(src, tmp_dest.name) - if self.selinux_enabled(): - self.set_context_if_different( - tmp_dest.name, context, False) + else: + dest_dir = os.path.dirname(dest) + dest_file = os.path.basename(dest) try: - tmp_stat = os.stat(tmp_dest.name) - if dest_stat and (tmp_stat.st_uid != dest_stat.st_uid or tmp_stat.st_gid != dest_stat.st_gid): - os.chown(tmp_dest.name, dest_stat.st_uid, dest_stat.st_gid) - except OSError: + tmp_dest = tempfile.NamedTemporaryFile( + prefix=".ansible_tmp", dir=dest_dir, suffix=dest_file) + except (OSError, IOError): e = get_exception() - if e.errno != errno.EPERM: - raise - os.rename(tmp_dest.name, dest) - except (shutil.Error, OSError, IOError): - e = get_exception() - self.cleanup(tmp_dest.name) - self.fail_json(msg='Could not replace file: %s to %s: %s' % (src, dest, e)) + self.fail_json(msg='The destination directory (%s) is not writable by the current user.' % dest_dir) + + try: # leaves tmp file behind when sudo and not root + if switched_user and os.getuid() != 0: + # cleanup will happen by 'rm' of tempdir + # copy2 will preserve some metadata + shutil.copy2(src, tmp_dest.name) + else: + shutil.move(src, tmp_dest.name) + if self.selinux_enabled(): + self.set_context_if_different( + tmp_dest.name, context, False) + try: + tmp_stat = os.stat(tmp_dest.name) + if dest_stat and (tmp_stat.st_uid != dest_stat.st_uid or tmp_stat.st_gid != dest_stat.st_gid): + os.chown(tmp_dest.name, dest_stat.st_uid, dest_stat.st_gid) + except OSError: + e = get_exception() + if e.errno != errno.EPERM: + raise + os.rename(tmp_dest.name, dest) + except (shutil.Error, OSError, IOError): + e = get_exception() + self.cleanup(tmp_dest.name) + self.fail_json(msg='Could not replace file: %s to %s: %s' % (src, dest, e)) if creating: # make sure the file has the correct permissions