From 3eb4a31431d62f806a377d776c5672c19a8a8f5b Mon Sep 17 00:00:00 2001 From: Trung Nguyen <57174311+trungnt2910@users.noreply.github.com> Date: Fri, 11 Apr 2025 12:51:10 +1000 Subject: [PATCH] Haiku: Add native library IO support Adds detection for non-portable filesystem and mount APIs and equivalent implementations using the Haiku API. --- src/native/libs/Common/pal_config.h.in | 2 + src/native/libs/System.Native/pal_io.c | 45 +++++++++++++++-- src/native/libs/System.Native/pal_mount.c | 60 +++++++++++++++++++++-- src/native/libs/configure.cmake | 8 +++ 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/src/native/libs/Common/pal_config.h.in b/src/native/libs/Common/pal_config.h.in index 99cd5990f39116..32176492bf488c 100644 --- a/src/native/libs/Common/pal_config.h.in +++ b/src/native/libs/Common/pal_config.h.in @@ -89,6 +89,7 @@ #cmakedefine01 HAVE_NETPACKET_PACKET_H #cmakedefine01 HAVE_NET_IF_ARP_H #cmakedefine01 HAVE_SYS_MNTENT_H +#cmakedefine01 HAVE_MNTENT_H #cmakedefine01 HAVE_NET_IFMEDIA_H #cmakedefine01 HAVE_IOS_NET_IFMEDIA_H #cmakedefine01 HAVE_LINUX_RTNETLINK_H @@ -130,6 +131,7 @@ #cmakedefine01 HAVE_TERMIOS_H #cmakedefine01 HAVE_DLFCN_H #cmakedefine01 HAVE_PTHREAD_H +#cmakedefine01 HAVE_SYS_STATFS_H #cmakedefine01 HAVE_SYS_STATVFS_H #cmakedefine01 HAVE_NET_IF_H #cmakedefine01 HAVE_SYS_PROCINFO_H diff --git a/src/native/libs/System.Native/pal_io.c b/src/native/libs/System.Native/pal_io.c index 23b226d74e0362..93ff59e0eaf15c 100644 --- a/src/native/libs/System.Native/pal_io.c +++ b/src/native/libs/System.Native/pal_io.c @@ -47,7 +47,7 @@ #include #elif HAVE_STATFS_MOUNT // BSD #include -#elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS // SunOS +#elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS && HAVE_STATVFS_BASETYPE // SunOS #include #include #if HAVE_STATFS_VFS @@ -59,6 +59,10 @@ #include #endif +#ifdef TARGET_HAIKU +#include +#endif // TARGET_HAIKU + #ifdef _AIX #include // Somehow, AIX mangles the definition for this behind a C++ def @@ -402,7 +406,7 @@ int32_t SystemNative_IsMemfdSupported(void) } #endif - // Note that the name has no affect on file descriptor behavior. From linux manpage: + // Note that the name has no affect on file descriptor behavior. From linux manpage: // Names do not affect the behavior of the file descriptor, and as such multiple files can have the same name without any side effects. int32_t fd = (int32_t)syscall(__NR_memfd_create, "test", MFD_CLOEXEC | MFD_ALLOW_SEALING); if (fd < 0) return 0; @@ -801,8 +805,14 @@ void SystemNative_GetDeviceIdentifiers(uint64_t dev, uint32_t* majorNumber, uint { #if !defined(TARGET_WASI) dev_t castedDev = (dev_t)dev; +#if !defined(TARGET_HAIKU) *majorNumber = (uint32_t)major(castedDev); *minorNumber = (uint32_t)minor(castedDev); +#else + // Haiku has no concept of major/minor numbers, but it does have device IDs. + *majorNumber = 0; + *minorNumber = (uint32_t)dev; +#endif // TARGET_HAIKU #else /* TARGET_WASI */ dev_t castedDev = (dev_t)dev; *majorNumber = 0; @@ -813,7 +823,12 @@ void SystemNative_GetDeviceIdentifiers(uint64_t dev, uint32_t* majorNumber, uint int32_t SystemNative_MkNod(const char* pathName, uint32_t mode, uint32_t major, uint32_t minor) { #if !defined(TARGET_WASI) +#if !defined(TARGET_HAIKU) dev_t dev = (dev_t)makedev(major, minor); +#else + (void)major; + dev_t dev = (dev_t)minor; +#endif // !TARGET_HAIKU int32_t result; while ((result = mknod(pathName, (mode_t)mode, dev)) < 0 && errno == EINTR); @@ -1560,7 +1575,7 @@ static int16_t ConvertLockType(int16_t managedLockType) } } -#if !HAVE_NON_LEGACY_STATFS || defined(TARGET_APPLE) || defined(TARGET_FREEBSD) +#if !HAVE_NON_LEGACY_STATFS || defined(TARGET_APPLE) || defined(TARGET_FREEBSD) || defined(TARGET_HAIKU) static uint32_t MapFileSystemNameToEnum(const char* fileSystemName) { uint32_t result = 0; @@ -1719,9 +1734,29 @@ uint32_t SystemNative_GetFileSystemType(intptr_t fd) uint32_t result = (uint32_t)statfsArgs.f_type; return result; #endif +#elif defined(TARGET_HAIKU) + struct stat st; + int fstatRes; + while ((fstatRes = fstat(ToFileDescriptor(fd), &st)) == -1 && errno == EINTR); + if (fstatRes == -1) return 0; + + struct fs_info info; + int fsStatDevRes; + while ((fsStatDevRes = fs_stat_dev(st.st_dev, &info)) == -1 && errno == EINTR); + if (fsStatDevRes == -1) return 0; + + if (strcmp(info.fsh_name, "bfs") == 0) + { + // Haiku names its own BFS filesystem "bfs", but on Linux and some other UNIXes + // it is called "befs" to avoid confusion with Boot File System. + strncpy(info.fsh_name, "befs", sizeof(info.fsh_name) - 1); + info.fsh_name[sizeof(info.fsh_name) - 1] = '\0'; + } + + return MapFileSystemNameToEnum(info.fsh_name); #elif defined(TARGET_WASI) return EINTR; -#elif !HAVE_NON_LEGACY_STATFS +#elif !HAVE_NON_LEGACY_STATFS && HAVE_STATVFS_BASETYPE int statfsRes; struct statvfs statfsArgs; while ((statfsRes = fstatvfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ; @@ -1895,7 +1930,7 @@ static int GetAllowedVectorCount(IOVector* vectors, int32_t vectorCount) // For macOS preadv and pwritev can fail with EINVAL when the total length // of all vectors overflows a 32-bit integer. size_t totalLength = 0; - for (int i = 0; i < allowedCount; i++) + for (int i = 0; i < allowedCount; i++) { assert(INT_MAX >= vectors[i].Count); diff --git a/src/native/libs/System.Native/pal_mount.c b/src/native/libs/System.Native/pal_mount.c index 386eba5ede1162..0f50c44c03ebf3 100644 --- a/src/native/libs/System.Native/pal_mount.c +++ b/src/native/libs/System.Native/pal_mount.c @@ -13,16 +13,24 @@ #if HAVE_MNTINFO #include #else +#if HAVE_SYS_STATFS_H #include +#endif #if HAVE_SYS_MNTENT_H #include #include -#include -#else +#elif HAVE_MNTENT_H #include #endif +#include #define STRING_BUFFER_SIZE 8192 +#ifdef __HAIKU__ +#include +#include +#include +#endif // __HAIKU__ + // Android does not define MNTOPT_RO #ifndef MNTOPT_RO #define MNTOPT_RO "r" @@ -68,7 +76,7 @@ int32_t SystemNative_GetAllMountPoints(MountPointFound onFound, void* context) return result; } -#else +#elif HAVE_MNTENT_H int result = -1; FILE* fp = setmntent("/proc/mounts", MNTOPT_RO); if (fp != NULL) @@ -91,6 +99,38 @@ int32_t SystemNative_GetAllMountPoints(MountPointFound onFound, void* context) return result; } +#elif defined(__HAIKU__) + int32 cookie = 0; + dev_t currentDev; + + while ((long)(currentDev = next_dev(&cookie)) >= 0) + { + struct fs_info info; + if (fs_stat_dev(currentDev, &info) != B_OK) + { + continue; + } + + char name[STRING_BUFFER_SIZE]; + // Two bytes for the name as we're storing "." + char buf[sizeof(struct dirent) + 2]; + struct dirent *entry = (struct dirent *)&buf; + strncpy(entry->d_name, ".", 2); + entry->d_pdev = currentDev; + entry->d_pino = info.root; + + if (get_path_for_dirent(entry, name, sizeof(name)) != B_OK) + { + continue; + } + + onFound(context, name); + } + + return 0; +} +#else +#error "Don't know how to enumerate mount points on this platform" #endif int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInformation* mpi) @@ -140,6 +180,9 @@ SystemNative_GetFileSystemTypeNameForMountPoint(const char* name, char* formatNa #if HAVE_NON_LEGACY_STATFS struct statfs stats; int result = statfs(name, &stats); +#elif defined(__HAIKU__) + struct fs_info stats; + int result = fs_stat_dev(dev_for_path(name), &stats); #else struct statvfs stats; int result = statvfs(name, &stats); @@ -167,6 +210,17 @@ SystemNative_GetFileSystemTypeNameForMountPoint(const char* name, char* formatNa } SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), stats.f_basetype); *formatType = -1; +#elif defined(__HAIKU__) + if (bufferLength < B_OS_NAME_LENGTH) + { + result = ERANGE; + *formatType = 0; + } + else + { + SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), stats.fsh_name); + *formatType = -1; + } #else SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), ""); *formatType = (int64_t)(stats.f_type); diff --git a/src/native/libs/configure.cmake b/src/native/libs/configure.cmake index 53437ece1546c1..42821749e8f6f5 100644 --- a/src/native/libs/configure.cmake +++ b/src/native/libs/configure.cmake @@ -886,6 +886,10 @@ check_include_files( "dlfcn.h" HAVE_DLFCN_H) +check_include_files( + "sys/statfs.h" + HAVE_SYS_STATFS_H) + check_include_files( "sys/statvfs.h" HAVE_SYS_STATVFS_H) @@ -959,6 +963,10 @@ check_include_files( "sys/mntent.h" HAVE_SYS_MNTENT_H) +check_include_files( + "mntent.h" + HAVE_MNTENT_H) + check_include_files( "stdint.h;net/if_media.h" HAVE_NET_IFMEDIA_H)