diff mbox series

[pseudo,v3,6/6] ports/linux/guts: Add open_tree_attr wrapper

Message ID 20260907111843.26746-7-frezidok1@gmail.com
State New
Headers show
Series Add open_tree() wrapper | expand

Commit Message

Dmitry Sakhonchik Sept. 7, 2026, 11:18 a.m. UTC
From: Dmitry Sakhonchik <frezidok1@gmail.com>

[YOCTO #16379]

It mostly mirrors open_tree, with the additional
mount attribute arguments passed to the underlying syscall.

Signed-off-by: Dmitry Sakhonchik <frezidok1@gmail.com>
---
 ports/linux/guts/open_tree_attr.c | 48 +++++++++++++++++++++++++++++++
 ports/linux/portdefs.h            |  9 ++++++
 ports/linux/pseudo_wrappers.c     | 16 +++++++++++
 ports/linux/wrapfuncs.in          |  1 +
 pseudo_wrappers.c                 |  1 +
 5 files changed, 75 insertions(+)
 create mode 100644 ports/linux/guts/open_tree_attr.c
diff mbox series

Patch

diff --git a/ports/linux/guts/open_tree_attr.c b/ports/linux/guts/open_tree_attr.c
new file mode 100644
index 0000000..da0315c
--- /dev/null
+++ b/ports/linux/guts/open_tree_attr.c
@@ -0,0 +1,48 @@ 
+/*
+ * Copyright (c) 2026 Yocto Project
+ * guts/COPYRIGHT for information.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * int open_tree_attr(int dirfd, const char *path, unsigned int flags, struct mount_attr *attr, size_t size)
+ *	int rc = -1;
+ */
+
+	/* Mostly based on open_tree wrapper */
+
+	struct stat64 buf;
+	int save_errno;
+	char *pseudo_path;
+
+	if (real_open_tree_attr) {
+		pseudo_debug(PDBGF_SYSCALL, "open_tree_attr, calling open_tree_attr.\n");
+		rc = real_open_tree_attr(dirfd, path, flags, attr, size);
+	} else {
+		pseudo_debug(PDBGF_SYSCALL, "open_tree_attr, calling syscall.\n");
+		rc = real_syscall(SYS_open_tree_attr, dirfd, path, flags, attr, size);
+	}
+
+	pseudo_path = pseudo_root_path(__func__, __LINE__, dirfd, path, 0);
+
+	if (rc != -1) {
+		save_errno = errno;
+		int stat_rc;
+
+		stat_rc = real___fxstatat64(_STAT_VER, dirfd, pseudo_path, &buf, (flags & AT_SYMLINK_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+
+		pseudo_debug(PDBGF_FILE, "open_tree_attr(path %s), flags %o, stat rc %d, stat mode %o\n",
+			pseudo_path, flags, stat_rc, buf.st_mode);
+
+		if (stat_rc != -1) {
+			pseudo_client_op(OP_OPEN, 0, rc, dirfd, pseudo_path, &buf);
+		} else {
+			pseudo_debug(PDBGF_FILE, "open_tree_attr(fd %d, path %d/%s, flags %d) succeeded, but stat failed (%s).\n",
+				rc, dirfd, pseudo_path, flags, strerror(errno));
+			pseudo_client_op(OP_OPEN, 0, rc, dirfd, pseudo_path, 0);
+		}
+		errno = save_errno;
+	}
+
+/*	return rc;
+ * }
+ */
diff --git a/ports/linux/portdefs.h b/ports/linux/portdefs.h
index 565fed9..af8b8e8 100644
--- a/ports/linux/portdefs.h
+++ b/ports/linux/portdefs.h
@@ -91,3 +91,12 @@  extern int unshare(int flags);
 
 #define SYS_open_tree __NR_open_tree
 #endif
+
+#ifndef SYS_open_tree_attr
+
+#ifndef __NR_open_tree_attr
+#define __NR_open_tree_attr 467
+#endif
+
+#define SYS_open_tree_attr __NR_open_tree_attr
+#endif
diff --git a/ports/linux/pseudo_wrappers.c b/ports/linux/pseudo_wrappers.c
index 33cba2d..4141556 100644
--- a/ports/linux/pseudo_wrappers.c
+++ b/ports/linux/pseudo_wrappers.c
@@ -116,6 +116,22 @@  syscall(long number, ...) {
 #error SYS_open_tree not defined
 #endif
 
+#ifdef SYS_open_tree_attr
+	if (number == SYS_open_tree_attr) {
+		pseudo_debug(PDBGF_SYSCALL, "syscall, faking open_tree_attr.\n");
+		va_start(ap, number);
+		int dirfd = va_arg(ap, int);
+		const char *path = va_arg(ap, const char*);
+		unsigned int flags = va_arg(ap, unsigned int);
+		struct mount_attr *attr = va_arg(ap, struct mount_attr*);
+		size_t size = va_arg(ap, size_t);
+
+		return wrap_open_tree_attr(dirfd, path, flags, attr, size);
+	}
+#else
+#error SYS_open_tree_attr not defined
+#endif
+
 #ifdef SYS_renameat2
         /* Call out wrapper, expanding the variable arguments first */
 	if (number == SYS_renameat2) {
diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in
index a51e9a0..639d9a5 100644
--- a/ports/linux/wrapfuncs.in
+++ b/ports/linux/wrapfuncs.in
@@ -11,6 +11,7 @@  int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags
 int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
 int __openat_2(int dirfd, const char *path, int flags); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
 int open_tree(int dirfd, const char *path, unsigned int flags); /* noignore_path=1 */
+int open_tree_attr(int dirfd, const char *path, unsigned int flags, struct mount_attr *attr, size_t size); /* noignore_path=1 */
 int mknod(const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknod */
 int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknodat */
 int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */
diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c
index 112239b..78cdecf 100644
--- a/pseudo_wrappers.c
+++ b/pseudo_wrappers.c
@@ -37,6 +37,7 @@ 
 #include <grp.h>
 #include <pwd.h>
 #include <utime.h>
+#include <sys/mount.h>
 #ifdef PSEUDO_PORT_LINUX_STATVFS
 #include <sys/statvfs.h>
 #endif