MCPcopy Create free account
hub / github.com/F-Stack/f-stack / vn_fullpath_hardlink

Function vn_fullpath_hardlink

freebsd/kern/vfs_cache.c:3406–3487  ·  view source on GitHub ↗

* Resolve an arbitrary vnode to a pathname (taking care of hardlinks). * * Since the namecache does not track hardlinks, the caller is expected to first * look up the target vnode with SAVENAME | WANTPARENT flags passed to namei. * * Then we have 2 cases: * - if the found vnode is a directory, the path can be constructed just by * following names up the chain * - otherwise we populate th

Source from the content-addressed store, hash-verified

3404 * from the parent
3405 */
3406static int
3407vn_fullpath_hardlink(struct nameidata *ndp, char **retbuf, char **freebuf,
3408 size_t *buflen)
3409{
3410 char *buf, *tmpbuf;
3411 struct pwd *pwd;
3412 struct componentname *cnp;
3413 struct vnode *vp;
3414 size_t addend;
3415 int error;
3416 enum vtype type;
3417
3418 if (*buflen < 2)
3419 return (EINVAL);
3420 if (*buflen > MAXPATHLEN)
3421 *buflen = MAXPATHLEN;
3422
3423 buf = malloc(*buflen, M_TEMP, M_WAITOK);
3424
3425 addend = 0;
3426 vp = ndp->ni_vp;
3427 /*
3428 * Check for VBAD to work around the vp_crossmp bug in lookup().
3429 *
3430 * For example consider tmpfs on /tmp and realpath /tmp. ni_vp will be
3431 * set to mount point's root vnode while ni_dvp will be vp_crossmp.
3432 * If the type is VDIR (like in this very case) we can skip looking
3433 * at ni_dvp in the first place. However, since vnodes get passed here
3434 * unlocked the target may transition to doomed state (type == VBAD)
3435 * before we get to evaluate the condition. If this happens, we will
3436 * populate part of the buffer and descend to vn_fullpath_dir with
3437 * vp == vp_crossmp. Prevent the problem by checking for VBAD.
3438 *
3439 * This should be atomic_load(&vp->v_type) but it is illegal to take
3440 * an address of a bit field, even if said field is sized to char.
3441 * Work around the problem by reading the value into a full-sized enum
3442 * and then re-reading it with atomic_load which will still prevent
3443 * the compiler from re-reading down the road.
3444 */
3445 type = vp->v_type;
3446 type = atomic_load_int(&type);
3447 if (type == VBAD) {
3448 error = ENOENT;
3449 goto out_bad;
3450 }
3451 if (type != VDIR) {
3452 cnp = &ndp->ni_cnd;
3453 addend = cnp->cn_namelen + 2;
3454 if (*buflen < addend) {
3455 error = ENOMEM;
3456 goto out_bad;
3457 }
3458 *buflen -= addend;
3459 tmpbuf = buf + *buflen;
3460 tmpbuf[0] = '/';
3461 memcpy(&tmpbuf[1], cnp->cn_nameptr, cnp->cn_namelen);
3462 tmpbuf[addend - 1] = '\0';
3463 vp = ndp->ni_dvp;

Callers 1

kern___realpathatFunction · 0.85

Calls 8

mallocFunction · 0.85
vn_fullpath_any_smrFunction · 0.85
pwd_holdFunction · 0.85
vn_fullpath_dirFunction · 0.85
pwd_dropFunction · 0.85
vrefFunction · 0.70
freeFunction · 0.70
memcpyFunction · 0.50

Tested by

no test coverage detected