Fix three bugs in the Solaris extended-attribute write loop and harden it:
- the write() length stayed the full size rather than the remaining
(size - bufpos), so a short write would re-write from the wrong offset;
- on a failed or zero-byte write, bufpos = -1 wrapped to SIZE_MAX (bufpos is
size_t) and the final `bufpos > 0` test then returned success;
- an empty value (size == 0) returned failure because `bufpos > 0` was false.
Also don't let close() clobber the write error's errno, and report a close()
failure on an otherwise-successful write.
set_file_attrs() holds an O_RDONLY|O_NOFOLLOW fd (held_fd) for the entry's
regular-file/dir/FIFO inode so metadata is applied to the pinned inode rather
than by re-resolving the path, which a parent-symlink race could redirect.
- xattrs: the set/remove/list of -X xattrs use the f-variant calls on held_fd
(lib/sysxattrs gains the wrappers); a raced FIFO can't block the open
(O_NONBLOCK).
- ACLs (real root): get_acl_fdat()/set_acl_fdat() apply the ACL via lib/acl.c's
fd path (xacl_*_fd), or setxattrat(AT_SYMLINK_NOFOLLOW) on the dirfd+leaf for
a socket/device, covering both the access and default ACL. pack_smb_acl()+
change_sacl_perms() still build the entries, so the bytes written match
acl_set_file() exactly. With no safe primitive we skip rather than re-resolve
the path. The legacy path-based libacl calls remain only for the cross-tree
(no held dirfd) and non-Linux cases.
- --fake-super ACL-as-xattr writes/deletes also go through held_fd, closing the
last path-based metadata write under fake-super.