From 76b8f002e1aef2f3b7311178b810f3ed6f505b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= Date: Tue, 4 Nov 2014 20:47:04 +0100 Subject: [PATCH] Implement lseek(SEEK_END) on devices While the partitioning system does publish partitions as block devices and report their size in stat(), the old BeOS-style drivers have no means of reporting it this way. So we fall back to ioctl(B_GET_GEOMETRY) to find out the size. --- src/system/kernel/fs/vfs.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 22571c283f..845912c603 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5582,6 +5582,7 @@ file_seek(struct file_descriptor* descriptor, off_t pos, int seekType) { struct vnode* vnode = descriptor->u.vnode; off_t offset; + bool isDevice = false; FUNCTION(("file_seek(pos = %" B_PRIdOFF ", seekType = %d)\n", pos, seekType)); @@ -5592,13 +5593,16 @@ file_seek(struct file_descriptor* descriptor, off_t pos, int seekType) case S_IFSOCK: return ESPIPE; + // drivers publish block devices as chr, so pick both + case S_IFBLK: + case S_IFCHR: + isDevice = true; + break; // The Open Group Base Specs don't mention any file types besides pipes, // fifos, and sockets specially, so we allow seeking them. case S_IFREG: - case S_IFBLK: case S_IFDIR: case S_IFLNK: - case S_IFCHR: break; } @@ -5621,6 +5625,22 @@ file_seek(struct file_descriptor* descriptor, off_t pos, int seekType) return status; offset = stat.st_size; + + if (offset == 0 && isDevice) { + // stat() on regular drivers doesn't report size + device_geometry geometry; + + if (HAS_FS_CALL(vnode, ioctl)) { + status = FS_CALL(vnode, ioctl, descriptor->cookie, + B_GET_GEOMETRY, &geometry, sizeof(geometry)); + if (status == B_OK) + offset = (off_t)geometry.bytes_per_sector + * geometry.sectors_per_track + * geometry.cylinder_count + * geometry.head_count; + } + } + break; } default: