* Return directory entries. */
| 1377 | * Return directory entries. |
| 1378 | */ |
| 1379 | static int |
| 1380 | mqfs_readdir(struct vop_readdir_args *ap) |
| 1381 | { |
| 1382 | struct vnode *vp; |
| 1383 | struct mqfs_info *mi; |
| 1384 | struct mqfs_node *pd; |
| 1385 | struct mqfs_node *pn; |
| 1386 | struct dirent entry; |
| 1387 | struct uio *uio; |
| 1388 | const void *pr_root; |
| 1389 | int *tmp_ncookies = NULL; |
| 1390 | off_t offset; |
| 1391 | int error, i; |
| 1392 | |
| 1393 | vp = ap->a_vp; |
| 1394 | mi = VFSTOMQFS(vp->v_mount); |
| 1395 | pd = VTON(vp); |
| 1396 | uio = ap->a_uio; |
| 1397 | |
| 1398 | if (vp->v_type != VDIR) |
| 1399 | return (ENOTDIR); |
| 1400 | |
| 1401 | if (uio->uio_offset < 0) |
| 1402 | return (EINVAL); |
| 1403 | |
| 1404 | if (ap->a_ncookies != NULL) { |
| 1405 | tmp_ncookies = ap->a_ncookies; |
| 1406 | *ap->a_ncookies = 0; |
| 1407 | ap->a_ncookies = NULL; |
| 1408 | } |
| 1409 | |
| 1410 | error = 0; |
| 1411 | offset = 0; |
| 1412 | |
| 1413 | pr_root = ap->a_cred->cr_prison->pr_root; |
| 1414 | sx_xlock(&mi->mi_lock); |
| 1415 | |
| 1416 | LIST_FOREACH(pn, &pd->mn_children, mn_sibling) { |
| 1417 | entry.d_reclen = sizeof(entry); |
| 1418 | |
| 1419 | /* |
| 1420 | * Only show names within the same prison root directory |
| 1421 | * (or not associated with a prison, e.g. "." and ".."). |
| 1422 | */ |
| 1423 | if (pn->mn_pr_root != NULL && pn->mn_pr_root != pr_root) |
| 1424 | continue; |
| 1425 | if (!pn->mn_fileno) |
| 1426 | mqfs_fileno_alloc(mi, pn); |
| 1427 | entry.d_fileno = pn->mn_fileno; |
| 1428 | entry.d_off = offset + entry.d_reclen; |
| 1429 | for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i) |
| 1430 | entry.d_name[i] = pn->mn_name[i]; |
| 1431 | entry.d_namlen = i; |
| 1432 | switch (pn->mn_type) { |
| 1433 | case mqfstype_root: |
| 1434 | case mqfstype_dir: |
| 1435 | case mqfstype_this: |
| 1436 | case mqfstype_parent: |
nothing calls this directly
no test coverage detected