Refactor ioctl input/output buffer size handling
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user