Refactor ioctl input/output buffer size handling

This commit is contained in:
Kim Woelders
2018-07-17 15:37:11 +02:00
parent 45e73de4b9
commit 2c3441dda5
+35 -79
View File
@@ -559,6 +559,11 @@ static const char *_ioctl_name(int cmd)
}
}
#define CHECK_BUF_IN(sz) \
if (in_bufsz < sz) do { in_bufsz = sz; goto retry_in; } while(0)
#define CHECK_BUF_OUT(sz) \
if (out_bufsz < sz) do { out_bufsz = sz; goto retry_out; } while(0)
static void
ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
struct fuse_file_info *info, unsigned int flags,
@@ -581,12 +586,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
case TCSETSF:
case TCSETSW:
case TCSETS:
if (!in_bufsz)
{
struct iovec iov = { arg, sizeof(struct termios) };
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
}
else
CHECK_BUF_IN(sizeof(struct termios));
{
speed_t speed;
int csize, par, sb;
@@ -650,45 +650,20 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
}
break;
case TCGETS:
if (out_bufsz)
{
fuse_reply_ioctl(req, 0, &tio, sizeof(struct termio));
}
else
{
struct iovec iov = { arg, sizeof(struct termio) };
fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
}
CHECK_BUF_OUT(sizeof(struct termios));
fuse_reply_ioctl(req, 0, &tio, sizeof(struct termios));
break;
case TIOCINQ: /* Get the number of bytes in the input
* buffer */
if (out_bufsz)
{
size_t rx_size = _read_avail(tty);
fuse_reply_ioctl(req, 0, &rx_size, sizeof(size_t));
}
else
{
struct iovec iov = { arg, sizeof(size_t) };
fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
}
CHECK_BUF_OUT(sizeof(int));
val = _read_avail(tty);
fuse_reply_ioctl(req, 0, &val, sizeof(int));
break;
case TIOCOUTQ: /* Get the number of bytes in the output
* buffer */
if (out_bufsz)
{
size_t tx_size = _write_avail(tty);
fuse_reply_ioctl(req, 0, &tx_size, sizeof(size_t));
}
else
{
struct iovec iov = { arg, sizeof(size_t) };
fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
}
CHECK_BUF_OUT(sizeof(int));
val = _write_avail(tty);
fuse_reply_ioctl(req, 0, &val, sizeof(int));
break;
case TCFLSH:
if (arg == TCIFLUSH)
@@ -711,7 +686,6 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
pthread_mutex_lock(&tty->tty_lock);
tty->blen = 0;
pthread_mutex_unlock(&tty->tty_lock);
fuse_reply_ioctl(req, 0, 0, 0);
break;
case TCOFLUSH:
@@ -725,27 +699,13 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
fuse_reply_ioctl(req, 0, 0, 0);
break;
case TIOCMGET:
if (out_bufsz)
{
fuse_reply_ioctl(req, 0, &mcr, sizeof(unsigned int));
}
else
{
struct iovec iov = { arg, sizeof(unsigned int) };
fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
}
CHECK_BUF_OUT(sizeof(int));
fuse_reply_ioctl(req, 0, &mcr, sizeof(int));
break;
case TIOCMBIS:
if (!in_bufsz)
{
struct iovec iov = { arg, sizeof(unsigned int) };
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
}
else
{
CHECK_BUF_IN(sizeof(int));
tiocm = *(unsigned int *)in_buf;
fuse_reply_ioctl(req, 0, 0, 0);
}
if (tiocm & TIOCM_RTS)
{
mcr |= TIOCM_RTS;
@@ -758,16 +718,9 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
}
break;
case TIOCMBIC:
if (!in_bufsz)
{
struct iovec iov = { arg, sizeof(unsigned int) };
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
}
else
{
CHECK_BUF_IN(sizeof(int));
tiocm = *(unsigned int *)in_buf;
fuse_reply_ioctl(req, 0, 0, 0);
}
if (tiocm & TIOCM_RTS)
{
mcr &= ~TIOCM_RTS;
@@ -780,13 +733,7 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
}
break;
case TIOCMSET:
if (!in_bufsz)
{
struct iovec iov = { arg, sizeof(unsigned int) };
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
}
else
{
CHECK_BUF_IN(sizeof(int));
tiocm = *(unsigned int *)in_buf;
fuse_reply_ioctl(req, 0, 0, 0);
@@ -799,26 +746,35 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
TNS_CTL_DTR_ON : TNS_CTL_DTR_OFF);
telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_RTS) ?
TNS_CTL_RTS_ON : TNS_CTL_RTS_OFF);
}
break;
case TCSBRK:
fuse_reply_ioctl(req, 0, 0, 0);
break;
case TIOCGWINSZ:
if (out_bufsz)
CHECK_BUF_OUT(sizeof(struct winsize));
{
struct winsize ws = {.ws_row = 25,.ws_col = 80 };
fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize));
}
else
break;
default:
fuse_reply_err(req, ENOSYS);
break;
retry_in:
{
struct iovec iov = { arg, sizeof(struct winsize) };
struct iovec iov = { arg, in_bufsz };
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
}
break;
retry_out:
{
struct iovec iov = { arg, out_bufsz };
fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
}
break;
default:
fuse_reply_err(req, ENOSYS);
return;
}
}