| 286 | } |
| 287 | |
| 288 | static int |
| 289 | get_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, |
| 290 | int dirbuflen, off_t *off, char **cpos, int *len, |
| 291 | int *eofflag, struct thread *td) |
| 292 | { |
| 293 | int error, reclen; |
| 294 | struct uio uio; |
| 295 | struct iovec iov; |
| 296 | struct dirent *dp; |
| 297 | |
| 298 | KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); |
| 299 | KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); |
| 300 | |
| 301 | if (*len == 0) { |
| 302 | iov.iov_base = dirbuf; |
| 303 | iov.iov_len = dirbuflen; |
| 304 | |
| 305 | uio.uio_iov = &iov; |
| 306 | uio.uio_iovcnt = 1; |
| 307 | uio.uio_offset = *off; |
| 308 | uio.uio_resid = dirbuflen; |
| 309 | uio.uio_segflg = UIO_SYSSPACE; |
| 310 | uio.uio_rw = UIO_READ; |
| 311 | uio.uio_td = td; |
| 312 | |
| 313 | *eofflag = 0; |
| 314 | |
| 315 | #ifdef MAC |
| 316 | error = mac_vnode_check_readdir(td->td_ucred, vp); |
| 317 | if (error == 0) |
| 318 | #endif |
| 319 | error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag, |
| 320 | NULL, NULL); |
| 321 | if (error) |
| 322 | return (error); |
| 323 | |
| 324 | *off = uio.uio_offset; |
| 325 | |
| 326 | *cpos = dirbuf; |
| 327 | *len = (dirbuflen - uio.uio_resid); |
| 328 | |
| 329 | if (*len == 0) |
| 330 | return (ENOENT); |
| 331 | } |
| 332 | |
| 333 | dp = (struct dirent *)(*cpos); |
| 334 | reclen = dp->d_reclen; |
| 335 | *dpp = dp; |
| 336 | |
| 337 | /* check for malformed directory.. */ |
| 338 | if (reclen < DIRENT_MINSIZE) |
| 339 | return (EINVAL); |
| 340 | |
| 341 | *cpos += reclen; |
| 342 | *len -= reclen; |
| 343 | |
| 344 | return (0); |
| 345 | } |
no test coverage detected