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
|
static void
|
||||||
ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
||||||
struct fuse_file_info *info, unsigned int flags,
|
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 TCSETSF:
|
||||||
case TCSETSW:
|
case TCSETSW:
|
||||||
case TCSETS:
|
case TCSETS:
|
||||||
if (!in_bufsz)
|
CHECK_BUF_IN(sizeof(struct termios));
|
||||||
{
|
|
||||||
struct iovec iov = { arg, sizeof(struct termios) };
|
|
||||||
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
speed_t speed;
|
speed_t speed;
|
||||||
int csize, par, sb;
|
int csize, par, sb;
|
||||||
@@ -650,45 +650,20 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TCGETS:
|
case TCGETS:
|
||||||
if (out_bufsz)
|
CHECK_BUF_OUT(sizeof(struct termios));
|
||||||
{
|
fuse_reply_ioctl(req, 0, &tio, sizeof(struct termios));
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TIOCINQ: /* Get the number of bytes in the input
|
case TIOCINQ: /* Get the number of bytes in the input
|
||||||
* buffer */
|
* buffer */
|
||||||
if (out_bufsz)
|
CHECK_BUF_OUT(sizeof(int));
|
||||||
{
|
val = _read_avail(tty);
|
||||||
size_t rx_size = _read_avail(tty);
|
fuse_reply_ioctl(req, 0, &val, sizeof(int));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TIOCOUTQ: /* Get the number of bytes in the output
|
case TIOCOUTQ: /* Get the number of bytes in the output
|
||||||
* buffer */
|
* buffer */
|
||||||
if (out_bufsz)
|
CHECK_BUF_OUT(sizeof(int));
|
||||||
{
|
val = _write_avail(tty);
|
||||||
size_t tx_size = _write_avail(tty);
|
fuse_reply_ioctl(req, 0, &val, sizeof(int));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TCFLSH:
|
case TCFLSH:
|
||||||
if (arg == TCIFLUSH)
|
if (arg == TCIFLUSH)
|
||||||
@@ -711,7 +686,6 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
pthread_mutex_lock(&tty->tty_lock);
|
pthread_mutex_lock(&tty->tty_lock);
|
||||||
tty->blen = 0;
|
tty->blen = 0;
|
||||||
pthread_mutex_unlock(&tty->tty_lock);
|
pthread_mutex_unlock(&tty->tty_lock);
|
||||||
|
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
case TCOFLUSH:
|
case TCOFLUSH:
|
||||||
@@ -725,27 +699,13 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
case TIOCMGET:
|
case TIOCMGET:
|
||||||
if (out_bufsz)
|
CHECK_BUF_OUT(sizeof(int));
|
||||||
{
|
fuse_reply_ioctl(req, 0, &mcr, sizeof(int));
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TIOCMBIS:
|
case TIOCMBIS:
|
||||||
if (!in_bufsz)
|
CHECK_BUF_IN(sizeof(int));
|
||||||
{
|
tiocm = *(unsigned int *)in_buf;
|
||||||
struct iovec iov = { arg, sizeof(unsigned int) };
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tiocm = *(unsigned int *)in_buf;
|
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
|
||||||
}
|
|
||||||
if (tiocm & TIOCM_RTS)
|
if (tiocm & TIOCM_RTS)
|
||||||
{
|
{
|
||||||
mcr |= TIOCM_RTS;
|
mcr |= TIOCM_RTS;
|
||||||
@@ -758,16 +718,9 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TIOCMBIC:
|
case TIOCMBIC:
|
||||||
if (!in_bufsz)
|
CHECK_BUF_IN(sizeof(int));
|
||||||
{
|
tiocm = *(unsigned int *)in_buf;
|
||||||
struct iovec iov = { arg, sizeof(unsigned int) };
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tiocm = *(unsigned int *)in_buf;
|
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
|
||||||
}
|
|
||||||
if (tiocm & TIOCM_RTS)
|
if (tiocm & TIOCM_RTS)
|
||||||
{
|
{
|
||||||
mcr &= ~TIOCM_RTS;
|
mcr &= ~TIOCM_RTS;
|
||||||
@@ -780,45 +733,48 @@ ttynvt_ioctl(fuse_req_t req, int cmd, void *arg,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TIOCMSET:
|
case TIOCMSET:
|
||||||
if (!in_bufsz)
|
CHECK_BUF_IN(sizeof(int));
|
||||||
{
|
tiocm = *(unsigned int *)in_buf;
|
||||||
struct iovec iov = { arg, sizeof(unsigned int) };
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tiocm = *(unsigned int *)in_buf;
|
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
|
||||||
|
|
||||||
DBG("CFG ioctl: DTR=%c RTS=%c\n",
|
DBG("CFG ioctl: DTR=%c RTS=%c\n",
|
||||||
tiocm & TIOCM_DTR ? '1' : '0', tiocm & TIOCM_RTS ? '1' : '0');
|
tiocm & TIOCM_DTR ? '1' : '0', tiocm & TIOCM_RTS ? '1' : '0');
|
||||||
|
|
||||||
mcr &= ~(TIOCM_RTS | TIOCM_DTR);
|
mcr &= ~(TIOCM_RTS | TIOCM_DTR);
|
||||||
mcr |= tiocm & (TIOCM_RTS | TIOCM_DTR);
|
mcr |= tiocm & (TIOCM_RTS | TIOCM_DTR);
|
||||||
telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_DTR) ?
|
telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_DTR) ?
|
||||||
TNS_CTL_DTR_ON : TNS_CTL_DTR_OFF);
|
TNS_CTL_DTR_ON : TNS_CTL_DTR_OFF);
|
||||||
telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_RTS) ?
|
telnet_rfc2217_ctl(tty->tn, (tiocm & TIOCM_RTS) ?
|
||||||
TNS_CTL_RTS_ON : TNS_CTL_RTS_OFF);
|
TNS_CTL_RTS_ON : TNS_CTL_RTS_OFF);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case TCSBRK:
|
case TCSBRK:
|
||||||
fuse_reply_ioctl(req, 0, 0, 0);
|
fuse_reply_ioctl(req, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
case TIOCGWINSZ:
|
case TIOCGWINSZ:
|
||||||
if (out_bufsz)
|
CHECK_BUF_OUT(sizeof(struct winsize));
|
||||||
{
|
{
|
||||||
struct winsize ws = {.ws_row = 25,.ws_col = 80 };
|
struct winsize ws = {.ws_row = 25,.ws_col = 80 };
|
||||||
fuse_reply_ioctl(req, 0, &ws, sizeof(struct winsize));
|
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);
|
fuse_reply_ioctl_retry(req, NULL, 0, &iov, 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
fuse_reply_err(req, ENOSYS);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user