| 2382 | } |
| 2383 | |
| 2384 | int |
| 2385 | kern_statat(struct thread *td, int flag, int fd, const char *path, |
| 2386 | enum uio_seg pathseg, struct stat *sbp, |
| 2387 | void (*hook)(struct vnode *vp, struct stat *sbp)) |
| 2388 | { |
| 2389 | struct nameidata nd; |
| 2390 | int error; |
| 2391 | |
| 2392 | if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH)) != 0) |
| 2393 | return (EINVAL); |
| 2394 | |
| 2395 | NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_RESOLVE_BENEATH | |
| 2396 | AT_SYMLINK_NOFOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, |
| 2397 | pathseg, path, fd, &cap_fstat_rights, td); |
| 2398 | |
| 2399 | if ((error = namei(&nd)) != 0) |
| 2400 | return (error); |
| 2401 | error = VOP_STAT(nd.ni_vp, sbp, td->td_ucred, NOCRED, td); |
| 2402 | if (error == 0) { |
| 2403 | if (__predict_false(hook != NULL)) |
| 2404 | hook(nd.ni_vp, sbp); |
| 2405 | } |
| 2406 | NDFREE_NOTHING(&nd); |
| 2407 | vput(nd.ni_vp); |
| 2408 | #ifdef __STAT_TIME_T_EXT |
| 2409 | sbp->st_atim_ext = 0; |
| 2410 | sbp->st_mtim_ext = 0; |
| 2411 | sbp->st_ctim_ext = 0; |
| 2412 | sbp->st_btim_ext = 0; |
| 2413 | #endif |
| 2414 | #ifdef KTRACE |
| 2415 | if (KTRPOINT(td, KTR_STRUCT)) |
| 2416 | ktrstat_error(sbp, error); |
| 2417 | #endif |
| 2418 | return (error); |
| 2419 | } |
| 2420 | |
| 2421 | #if defined(COMPAT_FREEBSD11) |
| 2422 | /* |
no test coverage detected