##### SUMMARY
When using a module attempts to set the mode of a symlink, and the symlink target points to a read-only filesystem, then it may crash with an `OSError: [Errno 30] Read-only file system`.

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
`file` module, due to `ansible/module_utils/basic.py` line 1117, in a `module.set_mode_if_different(…)` call.

https://github.com/ansible/ansible/blob/35dcd231be4f0afe2e1ee7a53769b3de1cc5222f/lib/ansible/module_utils/basic.py#L1101-L1122

##### ANSIBLE VERSION
```
ansible 2.8.1
  python version = 3.7.3 (default, Mar 27 2019, 09:23:15) [Clang 10.0.1 (clang-1001.0.46.3)]
```

##### OS / ENVIRONMENT
OS on target host: Linux (or any platform where [`os.lchmod()` does not exist](https://mail.python.org/pipermail/docs/2011-February/003119.html)).

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- hosts: all
  tasks:
    - copy:
        dest: /tmp/fs.img
        content: "{{ '_' * 1048576 }}"

    - filesystem:
        type: vfat
        dev: /tmp/fs.img

    - mount:
        state: mounted
        path: /mnt/readonly_fs
        src: /tmp/fs.img
        fstype: vfat
        opts: ro

    - name: This succeeds
      file:
        state: link
        path: /tmp/some_symlink
        src: /mnt/readonly_fs/nonexistent
        follow: false
        force: true
        mode: 0757

    - name: This crashes
      file:
        state: link
        path: /tmp/some_other_symlink
        src: /mnt/readonly_fs
        follow: false
        force: true
        mode: 0757
```

##### EXPECTED RESULTS

The play should not fail, since `follow: false` should mean that the `chmod` only operates on `/tmp/some_symlink`, and never should never care about where it points.

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes -->
```paste below
PLAY [all] ******************************************************************************************

TASK [Gathering Facts] ******************************************************************************
ok: [target.example.org]

TASK [copy] *****************************************************************************************
changed: [target.example.org]

TASK [filesystem] ***********************************************************************************
changed: [target.example.org]

TASK [mount] ****************************************************************************************
changed: [target.example.org]

TASK [This succeeds] ********************************************************************************
changed: [target.example.org]

TASK [This crashes] *********************************************************************************
fatal: [target.example.org]: FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to target.example.org closed.\r\n",
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/root/.ansible/tmp/ansible-tmp-1561877445.915763-155915524570611/AnsiballZ_file.py\", line 114, in <module>\r\n    _ansiballz_main()\r\n  File \"/root/.ansible/tmp/ansible-tmp-1561877445.915763-155915524570611/AnsiballZ_file.py\", line 106, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/root/.ansible/tmp/ansible-tmp-1561877445.915763-155915524570611/AnsiballZ_file.py\", line 49, in invoke_module\r\n    imp.load_module('__main__', mod, module, MOD_DESC)\r\n  File \"/usr/lib/python3.6/imp.py\", line 235, in load_module\r\n    return load_source(name, filename, file)\r\n  File \"/usr/lib/python3.6/imp.py\", line 170, in load_source\r\n    module = _exec(spec, sys.modules[name])\r\n  File \"<frozen importlib._bootstrap>\", line 618, in _exec\r\n  File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\r\n  File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\r\n  File \"/tmp/ansible_file_payload_r219es0e/__main__.py\", line 921, in <module>\r\n  File \"/tmp/ansible_file_payload_r219es0e/__main__.py\", line 909, in main\r\n  File \"/tmp/ansible_file_payload_r219es0e/__main__.py\", line 742, in ensure_symlink\r\n  File \"/tmp/ansible_file_payload_r219es0e/ansible_file_payload.zip/ansible/module_utils/basic.py\", line 1339, in set_fs_attributes_if_different\r\n  File \"/tmp/ansible_file_payload_r219es0e/ansible_file_payload.zip/ansible/module_utils/basic.py\", line 1112, in set_mode_if_different\r\nOSError: [Errno 30] Read-only file system: b'/tmp/some_other_symlink'\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

PLAY RECAP ******************************************************************************************
target.example.org : ok=5    changed=4    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
```

kwargs['state'] = 'directory'
            elif os.stat(b_path).st_nlink > 1:
                kwargs['state'] = 'hard'
            else:
                kwargs['state'] = 'file'
            if HAVE_SELINUX and self.selinux_enabled():
                kwargs['secontext'] = ':'.join(self.selinux_context(path))
            kwargs['size'] = st[stat.ST_SIZE]
        return kwargs
    def _check_locale(self):
        '''
        Uses the locale module to test the currently set locale
        (per the LANG and LC_CTYPE environment settings)
        '''
        try:
            
            
            locale.setlocale(locale.LC_ALL, '')
        except locale.Error:
            
            
            
            locale.setlocale(locale.LC_ALL, 'C')
            os.environ['LANG'] = 'C'
            os.environ['LC_ALL'] = 'C'
            os.environ['LC_MESSAGES'] = 'C'
        except Exception as e:
            self.fail_json(msg="An unknown error was encountered while attempting to validate the locale: %s" %
                           to_native(e), exception=traceback.format_exc())
    def _handle_aliases(self, spec=None, param=None):