diff --git a/library/files/file b/library/files/file index bdfcdd1ea78..9ef61d0ce22 100644 --- a/library/files/file +++ b/library/files/file @@ -132,15 +132,6 @@ EXAMPLES = ''' - file: src=/file/to/link/to dest=/path/to/symlink owner=foo group=foo state=link ''' -def dolink(src, path, state, module): - try: - if state == 'hard': - os.link(src,path) - else: - os.symlink(src, path) - except OSError, e: - module.fail_json(path=path, msg='Error while linking: %s' % str(e)) - def main(): # FIXME: pass this around, should not use global @@ -203,7 +194,10 @@ def main(): prev_state = 'link' elif os.path.isdir(path): prev_state = 'directory' + elif os.stat(path).st_nlink > 1: + prev_state = 'hard' else: + # could be many other tings, but defaulting to file prev_state = 'file' if prev_state != 'absent' and state == 'absent': @@ -229,9 +223,7 @@ def main(): module.exit_json(path=path, changed=True) if prev_state != 'absent' and prev_state != state: - if force and prev_state == 'file' and state == 'link': - pass - else: + if not (force and prev_state == 'file' and state == 'link'): module.fail_json(path=path, msg='refusing to convert between %s and %s for %s' % (prev_state, state, src)) if prev_state == 'absent' and state == 'absent': @@ -279,43 +271,44 @@ def main(): module.fail_json(path=path, src=src, msg='src file does not exist') if prev_state == 'absent': - if module.check_mode: - module.exit_json(changed=True) - dolink(src, path, state, module) changed = True elif prev_state == 'link': old_src = os.readlink(path) if not os.path.isabs(old_src): old_src = os.path.join(os.path.dirname(path), old_src) if old_src != src: - if module.check_mode: - module.exit_json(changed=True) - os.unlink(path) - dolink(src, path, state, module) + changed = True + elif prev_state == 'hard': + if not (state == 'hard' and os.stat(path).st_ino == os.stat(src).st_ino): + if not force: + module.fail_json(dest=path, src=src, msg='Cannot link, different hard link exists at destination') changed = True elif prev_state == 'file': if not force: module.fail_json(dest=path, src=src, msg='Cannot link, file exists at destination') - else: - if module.check_mode: - module.exit_json(changed=True) - os.unlink(path) - dolink(src, path, state, module) - changed = True + changed = True else: module.fail_json(dest=path, src=src, msg='unexpected position reached') - # set modes owners and context as needed - - file_args = module.load_file_common_arguments(module.params) - changed = module.set_context_if_different(path, file_args['secontext'], changed) - changed = module.set_owner_if_different(path, file_args['owner'], changed) - changed = module.set_group_if_different(path, file_args['group'], changed) - changed = module.set_mode_if_different(path, file_args['mode'], changed) + if changed and not module.check_mode: + if prev_state != 'absent': + try: + os.unlink(path) + except OSError, e: + module.fail_json(path=path, msg='Error while removing existing target: %s' % str(e)) + try: + if state == 'hard': + os.link(src,path) + else: + os.symlink(src, path) + except OSError, e: + module.fail_json(path=path, msg='Error while linking: %s' % str(e)) + changed = module.set_file_attributes_if_different(file_args, changed) module.exit_json(dest=path, src=src, changed=changed) - module.fail_json(path=path, msg='unexpected position reached') + else: + module.fail_json(path=path, msg='unexpected position reached') # this is magic, see lib/ansible/module_common.py #<>