static void delete_device( struct device *device ) { struct ioctl_call *ioctl, *next; if (!device->manager) return; /* already deleted */ /* terminate all pending requests */ LIST_FOR_EACH_ENTRY_SAFE( ioctl, next, &device->requests, struct ioctl_call, dev_entry ) { list_remove( &ioctl->mgr_entry ); set_ioctl_result( ioctl, STATUS_FILE_DELETED, NULL, 0 ); } unlink_named_object( &device->obj ); list_remove( &device->entry ); device->manager = NULL; }
status_t FileDevice::Control(void* _cookie, int32 op, void* buffer, size_t length) { Cookie* cookie = (Cookie*)_cookie; switch (op) { case B_GET_DEVICE_SIZE: return set_ioctl_result( fFileSize > ~(size_t)0 ? ~(size_t)0 : (size_t)fFileSize, buffer, length); case B_SET_BLOCKING_IO: case B_SET_NONBLOCKING_IO: // TODO: Translate to O_NONBLOCK and pass on! return B_OK; case B_GET_READ_STATUS: case B_GET_WRITE_STATUS: // TODO: poll() the FD! return set_ioctl_result(true, buffer, length); case B_GET_ICON: return B_UNSUPPORTED; case B_GET_GEOMETRY: case B_GET_BIOS_GEOMETRY: { // fill in the geometry // Optimally we have only 1 block per sector and only one head. // Since we have only a uint32 for the cylinder count, this won't // work for files > 2TB. So, we set the head count to the minimally // possible value. off_t blocks = fFileSize / kBlockSize; uint32 heads = (blocks + 0xfffffffe) / 0xffffffff; if (heads == 0) heads = 1; device_geometry geometry; geometry.bytes_per_sector = kBlockSize; geometry.sectors_per_track = 1; geometry.cylinder_count = blocks / heads; geometry.head_count = heads; geometry.device_type = B_DISK; geometry.removable = false; geometry.read_only = false; geometry.write_once = false; return set_ioctl_result(geometry, buffer, length); } case B_GET_MEDIA_STATUS: return set_ioctl_result((status_t)B_OK, buffer, length); case B_SET_INTERRUPTABLE_IO: case B_SET_UNINTERRUPTABLE_IO: return B_OK; case B_FLUSH_DRIVE_CACHE: return fsync(cookie->fd) == 0 ? B_OK : errno; case B_GET_BIOS_DRIVE_ID: return set_ioctl_result((uint8)0xf8, buffer, length); case B_GET_DRIVER_FOR_DEVICE: case B_SET_DEVICE_SIZE: case B_SET_PARTITION: case B_FORMAT_DEVICE: case B_EJECT_DEVICE: case B_LOAD_MEDIA: case B_GET_NEXT_OPEN_DEVICE: default: return B_BAD_VALUE; } return B_OK; }