Commit 78c0953502 for qemu.org
commit 78c0953502d876e758274a0ebbdfa192b87e5b53
Author: Warner Losh <imp@bsdimp.com>
Date: Tue May 5 00:37:28 2026 -0600
bsd-user: Add os-extattr.c with ACL conversion functions
Add os-extattr.c with t2h_freebsd_acl, h2t_freebsd_acl, and
t2h_freebsd_acl_type helper functions for ACL operations. Add
os-extattr.c to the build and include os-extattr.h in the
syscall dispatcher.
Signed-off-by: Stacey Son <sson@FreeBSD.org>
Assisted-by: Claude Opus 4.6 (1M context)
Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Warner Losh <imp@bsdimp.com>
diff --git a/bsd-user/freebsd/meson.build b/bsd-user/freebsd/meson.build
index db531604ad..0fc779749d 100644
--- a/bsd-user/freebsd/meson.build
+++ b/bsd-user/freebsd/meson.build
@@ -4,6 +4,7 @@ bsd_syscall_nr = custom_target('bsd-syscall-h',
command: [sh, meson.current_source_dir() / 'scripts/syscallhdr.sh', '@INPUT@', '@OUTPUT@', 'FREEBSD'])
bsd_user_ss.add(files(
+ 'os-extattr.c',
'os-proc.c',
'os-socket.c',
'os-stat.c',
diff --git a/bsd-user/freebsd/os-extattr.c b/bsd-user/freebsd/os-extattr.c
new file mode 100644
index 0000000000..3456157b4d
--- /dev/null
+++ b/bsd-user/freebsd/os-extattr.c
@@ -0,0 +1,118 @@
+/*
+ * FreeBSD extend attributes and ACL conversions
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+
+#ifndef _ACL_PRIVATE
+#define _ACL_PRIVATE
+#endif
+#include <sys/acl.h>
+
+#include "qemu.h"
+#include "qemu-os.h"
+
+/*
+ * FreeBSD ACL conversion.
+ */
+abi_long t2h_freebsd_acl(struct acl *host_acl, abi_ulong target_addr)
+{
+ uint32_t i;
+ struct target_freebsd_acl *target_acl;
+
+ if (!lock_user_struct(VERIFY_READ, target_acl, target_addr, 1)) {
+ return -TARGET_EFAULT;
+ }
+ __get_user(host_acl->acl_maxcnt, &target_acl->acl_maxcnt);
+ __get_user(host_acl->acl_cnt, &target_acl->acl_cnt);
+
+ if (host_acl->acl_maxcnt > ACL_MAX_ENTRIES ||
+ host_acl->acl_cnt > ACL_MAX_ENTRIES) {
+ unlock_user_struct(target_acl, target_addr, 0);
+ return -TARGET_EINVAL;
+ }
+
+ for (i = 0; i < host_acl->acl_cnt; i++) {
+ __get_user(host_acl->acl_entry[i].ae_tag,
+ &target_acl->acl_entry[i].ae_tag);
+ __get_user(host_acl->acl_entry[i].ae_id,
+ &target_acl->acl_entry[i].ae_id);
+ __get_user(host_acl->acl_entry[i].ae_perm,
+ &target_acl->acl_entry[i].ae_perm);
+ __get_user(host_acl->acl_entry[i].ae_entry_type,
+ &target_acl->acl_entry[i].ae_entry_type);
+ __get_user(host_acl->acl_entry[i].ae_flags,
+ &target_acl->acl_entry[i].ae_flags);
+ }
+
+ unlock_user_struct(target_acl, target_addr, 0);
+ return 0;
+}
+
+abi_long h2t_freebsd_acl(abi_ulong target_addr, struct acl *host_acl)
+{
+ uint32_t i;
+ struct target_freebsd_acl *target_acl;
+
+ if (host_acl->acl_maxcnt > ACL_MAX_ENTRIES ||
+ host_acl->acl_cnt > ACL_MAX_ENTRIES) {
+ return -TARGET_EINVAL;
+ }
+
+ if (!lock_user_struct(VERIFY_WRITE, target_acl, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+
+ __put_user(host_acl->acl_maxcnt, &target_acl->acl_maxcnt);
+ __put_user(host_acl->acl_cnt, &target_acl->acl_cnt);
+
+ for (i = 0; i < host_acl->acl_cnt; i++) {
+ __put_user(host_acl->acl_entry[i].ae_tag,
+ &target_acl->acl_entry[i].ae_tag);
+ __put_user(host_acl->acl_entry[i].ae_id,
+ &target_acl->acl_entry[i].ae_id);
+ __put_user(host_acl->acl_entry[i].ae_perm,
+ &target_acl->acl_entry[i].ae_perm);
+ __put_user(host_acl->acl_entry[i].ae_entry_type,
+ &target_acl->acl_entry[i].ae_entry_type);
+ __put_user(host_acl->acl_entry[i].ae_flags,
+ &target_acl->acl_entry[i].ae_flags);
+ }
+
+ unlock_user_struct(target_acl, target_addr, 1);
+ return 0;
+}
+
+abi_long t2h_freebsd_acl_type(acl_type_t *host_type, abi_long target_type)
+{
+
+ switch (target_type) {
+ case TARGET_FREEBSD_ACL_TYPE_ACCESS_OLD:
+ *host_type = ACL_TYPE_ACCESS_OLD;
+ break;
+
+ case TARGET_FREEBSD_ACL_TYPE_DEFAULT_OLD:
+ *host_type = ACL_TYPE_DEFAULT_OLD;
+ break;
+
+ case TARGET_FREEBSD_ACL_TYPE_ACCESS:
+ *host_type = ACL_TYPE_ACCESS;
+ break;
+
+ case TARGET_FREEBSD_ACL_TYPE_DEFAULT:
+ *host_type = ACL_TYPE_DEFAULT;
+ break;
+
+ case TARGET_FREEBSD_ACL_TYPE_NFS4:
+ *host_type = ACL_TYPE_NFS4;
+ break;
+
+ default:
+ return -TARGET_EINVAL;
+ }
+ return 0;
+}
+
diff --git a/bsd-user/freebsd/os-syscall.c b/bsd-user/freebsd/os-syscall.c
index 0c729da0ab..f385034a53 100644
--- a/bsd-user/freebsd/os-syscall.c
+++ b/bsd-user/freebsd/os-syscall.c
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#define _ACL_PRIVATE
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qemu/path.h"
@@ -43,6 +44,7 @@
#include "bsd-socket.h"
/* BSD dependent syscall shims */
+#include "os-extattr.h"
#include "os-stat.h"
#include "os-proc.h"
#include "os-signal.h"