| 185 | } |
| 186 | |
| 187 | static int |
| 188 | ptsdev_write(struct file *fp, struct uio *uio, struct ucred *active_cred, |
| 189 | int flags, struct thread *td) |
| 190 | { |
| 191 | struct tty *tp = fp->f_data; |
| 192 | struct pts_softc *psc = tty_softc(tp); |
| 193 | char ib[256], *ibstart; |
| 194 | size_t iblen, rintlen; |
| 195 | int error = 0; |
| 196 | |
| 197 | if (uio->uio_resid == 0) |
| 198 | return (0); |
| 199 | |
| 200 | for (;;) { |
| 201 | ibstart = ib; |
| 202 | iblen = MIN(uio->uio_resid, sizeof ib); |
| 203 | error = uiomove(ib, iblen, uio); |
| 204 | |
| 205 | tty_lock(tp); |
| 206 | if (error != 0) { |
| 207 | iblen = 0; |
| 208 | goto done; |
| 209 | } |
| 210 | |
| 211 | /* |
| 212 | * When possible, avoid the slow path. rint_bypass() |
| 213 | * copies all input to the input queue at once. |
| 214 | */ |
| 215 | MPASS(iblen > 0); |
| 216 | do { |
| 217 | rintlen = ttydisc_rint_simple(tp, ibstart, iblen); |
| 218 | ibstart += rintlen; |
| 219 | iblen -= rintlen; |
| 220 | if (iblen == 0) { |
| 221 | /* All data written. */ |
| 222 | break; |
| 223 | } |
| 224 | |
| 225 | /* Maybe the device isn't used anyway. */ |
| 226 | if (psc->pts_flags & PTS_FINISHED) { |
| 227 | error = EIO; |
| 228 | goto done; |
| 229 | } |
| 230 | |
| 231 | /* Wait for more data. */ |
| 232 | if (fp->f_flag & O_NONBLOCK) { |
| 233 | error = EWOULDBLOCK; |
| 234 | goto done; |
| 235 | } |
| 236 | |
| 237 | /* Wake up users on the slave side. */ |
| 238 | ttydisc_rint_done(tp); |
| 239 | error = cv_wait_sig(&psc->pts_inwait, tp->t_mtx); |
| 240 | if (error != 0) |
| 241 | goto done; |
| 242 | } while (iblen > 0); |
| 243 | |
| 244 | if (uio->uio_resid == 0) |
nothing calls this directly
no test coverage detected