Skip to content

Haiku: Add native library IO support #114521

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/native/libs/Common/pal_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#cmakedefine01 HAVE_MNTINFO
#cmakedefine01 HAVE_STATFS_FSTYPENAME
#cmakedefine01 HAVE_STATVFS_FSTYPENAME
#cmakedefine01 HAVE_STATVFS_BASETYPE
#cmakedefine01 HAVE_NON_LEGACY_STATFS
#cmakedefine01 HAVE_STRCPY_S
#cmakedefine01 HAVE_STRLCPY
Expand Down Expand Up @@ -88,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
Expand Down Expand Up @@ -128,6 +130,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
Expand All @@ -141,6 +144,8 @@
#cmakedefine01 HAVE_MAKEDEV_SYSMACROSH
#cmakedefine01 HAVE_GETGRGID_R
#cmakedefine01 HAVE_TERMIOS2
#cmakedefine01 HAVE_DIRENT_NAME_SIZE
#cmakedefine01 DIRENT_NAME_SIZE

#ifndef HOST_WASI
#cmakedefine01 HAVE_GETRUSAGE
Expand Down
50 changes: 45 additions & 5 deletions src/native/libs/System.Native/pal_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
#include <sys/vfs.h>
#elif HAVE_STATFS_MOUNT // BSD
#include <sys/mount.h>
#elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS // SunOS
#elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS && HAVE_STATVFS_BASETYPE // SunOS
#include <sys/types.h>
#include <sys/statvfs.h>
#if HAVE_STATFS_VFS
Expand All @@ -58,6 +58,10 @@
#include <sys/param.h>
#endif

#ifdef TARGET_HAIKU
#include <fs_info.h>
#endif // TARGET_HAIKU

#ifdef _AIX
#include <alloca.h>
// Somehow, AIX mangles the definition for this behind a C++ def
Expand Down Expand Up @@ -399,7 +403,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;
Expand Down Expand Up @@ -515,8 +519,13 @@ int32_t SystemNative_GetReadDirRBufferSize(void)
#endif
// dirent should be under 2k in size
assert(result < 2048);
#if HAVE_DIRENT_NAME_SIZE
// add some extra space so we can align the buffer to dirent.
return (int32_t)(result + dirent_alignment - 1);
#else
// add some extra space for the name.
return sizeof(struct dirent) + NAME_MAX + dirent_alignment - 1;
#endif // HAVE_DIRENT_NAME_SIZE
#else
return 0;
#endif
Expand Down Expand Up @@ -882,8 +891,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;
Expand All @@ -894,7 +909,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);
Expand Down Expand Up @@ -1641,7 +1661,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;
Expand Down Expand Up @@ -1800,9 +1820,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) ;
Expand Down Expand Up @@ -1976,7 +2016,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);

Expand Down
60 changes: 57 additions & 3 deletions src/native/libs/System.Native/pal_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,24 @@
#if HAVE_MNTINFO
#include <sys/mount.h>
#else
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#if HAVE_SYS_MNTENT_H
#include <sys/mntent.h>
#include <sys/mnttab.h>
#include <sys/statvfs.h>
#else
#elif HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <sys/statvfs.h>
#define STRING_BUFFER_SIZE 8192

#ifdef __HAIKU__
#include <dirent.h>
#include <fs_info.h>
#include <fs_query.h>
#endif // __HAIKU__

// Android does not define MNTOPT_RO
#ifndef MNTOPT_RO
#define MNTOPT_RO "r"
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -140,6 +180,9 @@ SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer
#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);
Expand All @@ -166,6 +209,17 @@ SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer
assert(formatType != NULL);
*formatType = (int64_t)(stats.f_type);
SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), "");
#elif defined(__HAIKU__)
if (bufferLength < B_OS_NAME_LENGTH)
{
result = ERANGE;
*formatType = 0;
}
else
{
SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), stats.fsh_name);
*formatType = -1;
}
#else
*formatType = 0;
#endif
Expand Down
18 changes: 18 additions & 0 deletions src/native/libs/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,17 @@ check_struct_has_member(
"sys/mount.h"
HAVE_STATVFS_FSTYPENAME)

check_struct_has_member(
"struct statvfs"
f_basetype
"sys/statvfs.h"
HAVE_STATVFS_BASETYPE)

set(CMAKE_EXTRA_INCLUDE_FILES dirent.h)
check_type_size(
"((struct dirent*)0)->d_name"
DIRENT_NAME_SIZE)
set(CMAKE_EXTRA_INCLUDE_FILES)

# statfs: Find whether this struct exists
if (HAVE_STATFS_FSTYPENAME OR HAVE_STATVFS_FSTYPENAME)
Expand Down Expand Up @@ -882,6 +892,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)
Expand Down Expand Up @@ -955,6 +969,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)
Expand Down
Loading