return ret;
}
+
+abi_long do_bsd_ioctl(int fd, abi_long cmd, abi_long arg)
+{
+ const IOCTLEntry *ie;
+ const argtype *arg_type;
+ abi_long ret;
+ uint8_t buf_temp[MAX_STRUCT_SIZE];
+ int target_size;
+ void *argptr;
+
+ ie = ioctl_entries;
+ for (;;) {
+ if (ie->target_cmd == 0) {
+ gemu_log("QEMU unsupported ioctl: ");
+ log_unsupported_ioctl(cmd);
+ return -TARGET_ENOSYS;
+ }
+ if (ie->target_cmd == cmd) {
+ break;
+ }
+ ie++;
+ }
+ arg_type = ie->arg_type;
+#if defined(DEBUG)
+ gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
+#endif
+ if (ie->do_ioctl) {
+ return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
+ }
+
+ switch (arg_type[0]) {
+ case TYPE_NULL:
+ /* no argument */
+ ret = get_errno(safe_ioctl(fd, ie->host_cmd));
+ break;
+
+ case TYPE_PTRVOID:
+ case TYPE_INT:
+ /* int argument */
+ ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
+ break;
+
+ case TYPE_PTR:
+ arg_type++;
+ target_size = thunk_type_size(arg_type, 0);
+ switch (ie->access) {
+ case IOC_R:
+ ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+ if (!is_error(ret)) {
+ argptr = lock_user(VERIFY_WRITE, arg,
+ target_size, 0);
+ if (!argptr) {
+ return -TARGET_EFAULT;
+ }
+ thunk_convert(argptr, buf_temp, arg_type,
+ THUNK_TARGET);
+ unlock_user(argptr, arg, target_size);
+ }
+ break;
+
+ case IOC_W:
+ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+ if (!argptr) {
+ return -TARGET_EFAULT;
+ }
+ thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+ unlock_user(argptr, arg, 0);
+ ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+ break;
+
+ case IOC_RW:
+ /* fallthrough */
+ default:
+ argptr = lock_user(VERIFY_READ, arg, target_size, 1);
+ if (!argptr) {
+ return -TARGET_EFAULT;
+ }
+ thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
+ unlock_user(argptr, arg, 0);
+ ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
+ if (!is_error(ret)) {
+ argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
+ if (!argptr) {
+ return -TARGET_EFAULT;
+ }
+ thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
+ unlock_user(argptr, arg, target_size);
+ }
+ break;
+ }
+ break;
+
+ default:
+ gemu_log("QEMU unknown ioctl: type=%d ", arg_type[0]);
+ log_unsupported_ioctl(cmd);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ return ret;
+}