aboutsummaryrefslogtreecommitdiff
path: root/bsd-user
diff options
context:
space:
mode:
authorStacey Son <sson@FreeBSD.org>2023-08-13 10:41:41 +0200
committerWarner Losh <imp@bsdimp.com>2023-08-28 12:16:18 -0600
commit213444529de083d1cbd1ef2391a1323207182f93 (patch)
treeadb1d03f7e8acc955b2f310fe275ebe22211bc99 /bsd-user
parent191fe50d5dc8f26e0049d62e92d192d410520fab (diff)
bsd-user: Implement getdents related syscalls
Implement the following syscalls: getdents(2) getdirecentries(2) Signed-off-by: Stacey Son <sson@FreeBSD.org> Signed-off-by: Karim Taha <kariem.taha2.7@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Warner Losh <imp@bsdimp.com>
Diffstat (limited to 'bsd-user')
-rw-r--r--bsd-user/freebsd/os-stat.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/bsd-user/freebsd/os-stat.h b/bsd-user/freebsd/os-stat.h
index 9492c93c55..7dc41cd0bf 100644
--- a/bsd-user/freebsd/os-stat.h
+++ b/bsd-user/freebsd/os-stat.h
@@ -279,4 +279,76 @@ static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
return ret;
}
+/* getdents(2) */
+static inline abi_long do_freebsd11_getdents(abi_long arg1,
+ abi_ulong arg2, abi_long nbytes)
+{
+ abi_long ret;
+ struct freebsd11_dirent *dirp;
+
+ dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
+ if (dirp == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(freebsd11_getdents(arg1, (char *)dirp, nbytes));
+ if (!is_error(ret)) {
+ struct freebsd11_dirent *de;
+ int len = ret;
+ int reclen;
+
+ de = dirp;
+ while (len > 0) {
+ reclen = de->d_reclen;
+ if (reclen > len) {
+ return -TARGET_EFAULT;
+ }
+ de->d_reclen = tswap16(reclen);
+ de->d_fileno = tswap32(de->d_fileno);
+ len -= reclen;
+ }
+ }
+ return ret;
+}
+
+/* getdirecentries(2) */
+static inline abi_long do_freebsd_getdirentries(abi_long arg1,
+ abi_ulong arg2, abi_long nbytes, abi_ulong arg4)
+{
+ abi_long ret;
+ struct dirent *dirp;
+ long basep;
+
+ dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
+ if (dirp == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(getdirentries(arg1, (char *)dirp, nbytes, &basep));
+ if (!is_error(ret)) {
+ struct dirent *de;
+ int len = ret;
+ int reclen;
+
+ de = dirp;
+ while (len > 0) {
+ reclen = de->d_reclen;
+ if (reclen > len) {
+ return -TARGET_EFAULT;
+ }
+ de->d_fileno = tswap64(de->d_fileno);
+ de->d_off = tswap64(de->d_off);
+ de->d_reclen = tswap16(de->d_reclen);
+ de->d_namlen = tswap16(de->d_namlen);
+ len -= reclen;
+ de = (struct dirent *)((void *)de + reclen);
+ }
+ }
+ unlock_user(dirp, arg2, ret);
+ if (arg4) {
+ if (put_user(basep, arg4, abi_ulong)) {
+ return -TARGET_EFAULT;
+ }
+ }
+ return ret;
+}
+
#endif /* BSD_USER_FREEBSD_OS_STAT_H */