Samba cleans up and normalizes the account name, and this normalized name is what's used to fill in the %u macro in the smb.conf. tl;dr the behavior will never change, and it's better to just keep your account names lower-case.
Code:
root@adtest[~]# python3
Python 3.7.5 (default, Nov 15 2019, 13:07:21)
[Clang 8.0.0 (tags/RELEASE_800/final 356365)] on freebsd11
Type "help", "copyright", "credits" or "license" for more information.
>>> from middlewared.client import Client
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB')
{'uid': 65534, 'gid': 65534, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': True, 'APPEND_DATA': True, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': True, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': True, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': True, 'WRITE_OWNER': True, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': True, 'APPEND_DATA': True, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'everyone@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': False, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}]}
>>> new_acl = Client().call('filesystem.get_default_acl', 'RESTRICTED')
>>> print(new_acl)
[{'tag': 'owner@', 'id': None, 'perms': {'BASIC': 'FULL_CONTROL'}, 'flags': {'BASIC': 'INHERIT'}, 'type': 'ALLOW'}, {'tag': 'group@', 'id': None, 'perms': {'BASIC': 'MODIFY'}, 'flags': {'BASIC': 'INHERIT'}, 'type': 'ALLOW'}]
>>> Client().call('filesystem.setacl', {'path': '/mnt/dozer/SMB', 'dacl': new_acl, 'options': {}})
41
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB')
{'uid': 65534, 'gid': 65534, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'FULL_CONTROL'}, 'flags': {'BASIC': 'INHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'MODIFY'}, 'flags': {'BASIC': 'INHERIT'}}]}
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB/testfile')
{'uid': 0, 'gid': 65534, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': True, 'APPEND_DATA': True, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': True, 'EXECUTE': False, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': True, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': True, 'WRITE_OWNER': True, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': False, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'everyone@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': False, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}]}
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB/testdir')
{'uid': 0, 'gid': 65534, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': True, 'APPEND_DATA': True, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': True, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': True, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': True, 'WRITE_OWNER': True, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'everyone@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}]}
>>> Client().call('filesystem.setacl', {'path': '/mnt/dozer/SMB', 'dacl': new_acl, 'options': {'recursive': True}})
44
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB/testfile')
{'uid': 0, 'gid': 65534, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'FULL_CONTROL'}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'MODIFY'}, 'flags': {'BASIC': 'NOINHERIT'}}]}
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB/testdir')
{'uid': 0, 'gid': 65534, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'FULL_CONTROL'}, 'flags': {'BASIC': 'INHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'MODIFY'}, 'flags': {'BASIC': 'INHERIT'}}]}
I don't see this issue. Sorry if the chunk is somewhat illegible. Those are the middleware API calls to manipulate the ACL. Here is the case of a subdataset:
Code:
root@adtest[~]# zfs create dozer/SMB/subdataset
root@adtest[~]# python3
Python 3.7.5 (default, Nov 15 2019, 13:07:21)
[Clang 8.0.0 (tags/RELEASE_800/final 356365)] on freebsd11
Type "help", "copyright", "credits" or "license" for more information.
>>> from middlewared.client import Client
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB/subdataset')
{'uid': 0, 'gid': 0, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': True, 'APPEND_DATA': True, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': True, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': True, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': True, 'WRITE_OWNER': True, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}, {'tag': 'everyone@', 'id': None, 'type': 'ALLOW', 'perms': {'READ_DATA': True, 'WRITE_DATA': False, 'APPEND_DATA': False, 'READ_NAMED_ATTRS': True, 'WRITE_NAMED_ATTRS': False, 'EXECUTE': True, 'DELETE_CHILD': False, 'READ_ATTRIBUTES': True, 'WRITE_ATTRIBUTES': False, 'DELETE': False, 'READ_ACL': True, 'WRITE_ACL': False, 'WRITE_OWNER': False, 'SYNCHRONIZE': True}, 'flags': {'BASIC': 'NOINHERIT'}}]}
>>> new_acl = Client().call('filesystem.get_default_acl', 'RESTRICTED')
>>> Client().call('filesystem.setacl', {'path': '/mnt/dozer/SMB', 'dacl': new_acl, 'options': {'recursive': True, 'traverse': True}})
53
>>> Client().call('filesystem.getacl', '/mnt/dozer/SMB/subdataset')
{'uid': 0, 'gid': 0, 'acl': [{'tag': 'owner@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'FULL_CONTROL'}, 'flags': {'BASIC': 'INHERIT'}}, {'tag': 'group@', 'id': None, 'type': 'ALLOW', 'perms': {'BASIC': 'MODIFY'}, 'flags': {'BASIC': 'INHERIT'}}]}
If the goal is to change the owner UID and group GID, then you will need to alter the form from what it is currently showing. The reason for this is changing owner and group is generally not desirable for our enterprise user. File ownership can be like a fingerprint showing who created the file. If you change the owner, then the webui will send an API call with the appropriate UID, and file ownership will be changed.
The "recursive" checkbox applies the changes recursively inside the dataset. The "traverse" checkbox applies it to all child datasets.