From 36d7c0c403b7ac9c53580613fb41e13e4fd41fdf Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Mon, 17 Apr 2017 15:05:10 -0700 Subject: [PATCH] Fix places where path needs to be bytes on python3 These were discovered on python3 with fetch code that fails on errors. Probably could be provoked with particular sets of arguments to stat as well. --- lib/ansible/module_utils/basic.py | 16 ++++++++++++---- lib/ansible/modules/files/stat.py | 12 ++++++------ test/units/module_utils/test_basic.py | 6 ++++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 70ee924a3a8..dd30ba9b3e0 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -915,10 +915,18 @@ class AnsibleModule(object): return (uid, gid) def find_mount_point(self, path): - path = os.path.realpath(os.path.expanduser(os.path.expandvars(path))) - while not os.path.ismount(path): - path = os.path.dirname(path) - return path + path_is_bytes = False + if isinstance(path, binary_type): + path_is_bytes = True + + b_path = os.path.realpath(to_bytes(os.path.expanduser(os.path.expandvars(path)), errors='surrogate_or_strict')) + while not os.path.ismount(b_path): + b_path = os.path.dirname(b_path) + + if path_is_bytes: + return b_path + + return to_text(b_path, errors='surrogate_or_strict') def is_special_selinux_path(self, path): """ diff --git a/lib/ansible/modules/files/stat.py b/lib/ansible/modules/files/stat.py index 508791ea182..bea898be507 100644 --- a/lib/ansible/modules/files/stat.py +++ b/lib/ansible/modules/files/stat.py @@ -477,11 +477,11 @@ def main(): # resolved permissions for perm in [('readable', os.R_OK), ('writeable', os.W_OK), ('executable', os.X_OK)]: - output[perm[0]] = os.access(path, perm[1]) + output[perm[0]] = os.access(b_path, perm[1]) # symlink info if output.get('islnk'): - output['lnk_source'] = os.path.realpath(path) + output['lnk_source'] = os.path.realpath(b_path) try: # user data pw = pwd.getpwuid(st.st_uid) @@ -500,19 +500,19 @@ def main(): if get_md5: # Will fail on FIPS-140 compliant systems try: - output['md5'] = module.md5(path) + output['md5'] = module.md5(b_path) except ValueError: output['md5'] = None if get_checksum: - output['checksum'] = module.digest_from_file(path, checksum_algorithm) + output['checksum'] = module.digest_from_file(b_path, checksum_algorithm) # try to get mime data if requested if get_mime: output['mimetype'] = output['charset'] = 'unknown' mimecmd = module.get_bin_path('file') if mimecmd: - mimecmd = [mimecmd, '-i', path] + mimecmd = [mimecmd, '-i', b_path] try: rc, out, err = module.run_command(mimecmd) if rc == 0: @@ -527,7 +527,7 @@ def main(): output['version'] = None output['attributes'] = [] output['attr_flags'] = '' - out = module.get_file_attributes(path) + out = module.get_file_attributes(b_path) for x in ('version', 'attributes', 'attr_flags'): if x in out: output[x] = out[x] diff --git a/test/units/module_utils/test_basic.py b/test/units/module_utils/test_basic.py index 526dca1c9cd..00cb013c78a 100644 --- a/test/units/module_utils/test_basic.py +++ b/test/units/module_utils/test_basic.py @@ -647,7 +647,7 @@ class TestModuleUtilsBasic(ModuleTestCase): ) def _mock_ismount(path): - if path == '/': + if path == b'/': return True return False @@ -655,7 +655,9 @@ class TestModuleUtilsBasic(ModuleTestCase): self.assertEqual(am.find_mount_point('/root/fs/../mounted/path/to/whatever'), '/') def _mock_ismount(path): - if path == '/subdir/mount': + if path == b'/subdir/mount': + return True + if path == b'/': return True return False