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.
This commit is contained in:
François Revol 2014-11-04 20:47:04 +01:00
parent b7ff6340ae
commit 76b8f002e1
1 changed files with 22 additions and 2 deletions

View File

@ -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: