diff --git a/src/tests/add-ons/kernel/file_systems/bfs/bfs_shell/Jamfile b/src/tests/add-ons/kernel/file_systems/bfs/bfs_shell/Jamfile index 189c2ba466..ae6fe68484 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/bfs_shell/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/bfs/bfs_shell/Jamfile @@ -53,6 +53,7 @@ SYSHDRS = $(HAIKU_HDRS) ; close=build_platform_close fstat=build_platform_fstat read_pos=build_platform_read_pos + ioctl=build_platform_ioctl ; } diff --git a/src/tests/add-ons/kernel/file_systems/fs_shell/sysdep.c b/src/tests/add-ons/kernel/file_systems/fs_shell/sysdep.c index aea21df996..5d9d490831 100644 --- a/src/tests/add-ons/kernel/file_systems/fs_shell/sysdep.c +++ b/src/tests/add-ons/kernel/file_systems/fs_shell/sysdep.c @@ -15,13 +15,20 @@ */ #include "compat.h" +#include #include #include #include +#include #include #include "stat_util.h" +// Linux support +#ifdef HAIKU_HOST_PLATFORM_LINUX +# include +#endif // HAIKU_HOST_PLATFORM_LINUX + // Let the FS think, we are the root user. uid_t @@ -200,7 +207,7 @@ readv_pos(int fd, fs_off_t _pos, const struct iovec *iov, int count) off_t pos = (off_t)_pos; size_t amt = 0; ssize_t ret; - struct iovec *tmpiov; + const struct iovec *tmpiov; int i, n; if (lseek(fd, pos, SEEK_SET) < 0) { @@ -235,7 +242,7 @@ writev_pos(int fd, fs_off_t _pos, const struct iovec *iov, int count) off_t pos = (off_t)_pos; size_t amt = 0; ssize_t ret; - struct iovec *tmpiov; + const struct iovec *tmpiov; int i, n; if (lseek(fd, pos, SEEK_SET) < 0) { @@ -333,6 +340,110 @@ build_platform_read_pos(int fd, fs_off_t pos, void *buf, size_t count) } +#ifdef HAIKU_HOST_PLATFORM_LINUX + +static bool +test_size(int fd, off_t size) +{ + char buffer[1]; + + if (size == 0) + return true; + + if (lseek(fd, size - 1, SEEK_SET) < 0) + return false; + + return (read(fd, &buffer, 1) == 1); +} + + +static off_t +get_partition_size(int fd, off_t maxSize) +{ + // binary search + off_t lower = 0; + off_t upper = maxSize; + while (lower < upper) { + off_t mid = (lower + upper + 1) / 2; + if (test_size(fd, mid)) + lower = mid; + else + upper = mid - 1; + } + + return lower; +} + +#endif // HAIKU_HOST_PLATFORM_LINUX + + +extern int build_platform_ioctl(int fd, unsigned long op, ...); + +int +build_platform_ioctl(int fd, unsigned long op, ...) +{ + status_t error = FS_BAD_VALUE; + va_list list; + + // count arguments + + va_start(list, op); + + switch (op) { + case 7: // B_GET_GEOMETRY + { + #ifdef HAIKU_HOST_PLATFORM_LINUX + { + device_geometry *geometry = va_arg(list, device_geometry*); + struct hd_geometry hdGeometry; + // BLKGETSIZE and BLKGETSIZE64 don't seem to work for + // partitions. So we get the device geometry (there only seems + // to be HDIO_GETGEO, which is kind of obsolete, BTW), and + // get the partition size via binary search. + if (ioctl(fd, HDIO_GETGEO, &hdGeometry) == 0) { + off_t bytesPerCylinder = (off_t)hdGeometry.heads + * hdGeometry.sectors * 512; + off_t deviceSize = bytesPerCylinder * hdGeometry.cylinders; + off_t partitionSize = get_partition_size(fd, deviceSize); + + geometry->head_count = hdGeometry.heads; + geometry->cylinder_count = partitionSize / bytesPerCylinder; + geometry->sectors_per_track = hdGeometry.sectors; + + // TODO: Get the real values... + geometry->bytes_per_sector = 512; + geometry->device_type = B_DISK; + geometry->removable = false; + geometry->read_only = false; + geometry->write_once = false; + error = FS_OK; + } else + error = from_platform_error(errno); + } + #endif // HAIKU_HOST_PLATFORM_LINUX + + break; + } + + case 20: // B_FLUSH_DRIVE_CACHE + error = FS_OK; + break; + + case 10000: // IOCTL_FILE_UNCACHED_IO + error = FS_OK; + break; + } + + va_end(list); + + if (error != FS_OK) { + errno = error; + return -1; + } + return 0; +} + + #endif /* ! __BEOS__ */