|
Lines 587-589
Link Here
|
| 587 |
return (error); |
587 |
return (error); |
| 588 |
} |
588 |
} |
| 589 |
|
589 |
|
|
|
590 |
/* |
| 591 |
* Thus begins the fullpath magic. |
| 592 |
*/ |
| 593 |
|
| 594 |
#undef STATNODE |
| 595 |
#define STATNODE(name) \ |
| 596 |
static u_int name; \ |
| 597 |
SYSCTL_INT(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, 0, "") |
| 598 |
|
| 599 |
static int disablefullpath; |
| 600 |
SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW, |
| 601 |
&disablefullpath, 0, ""); |
| 602 |
|
| 603 |
STATNODE(numfullpathcalls); |
| 604 |
STATNODE(numfullpathfail1); |
| 605 |
STATNODE(numfullpathfail2); |
| 606 |
STATNODE(numfullpathfail3); |
| 607 |
STATNODE(numfullpathfail4); |
| 608 |
STATNODE(numfullpathfound); |
| 609 |
|
| 610 |
int |
| 611 |
textvp_fullpath(struct proc *p, char **retbuf, char **retfreebuf) { |
| 612 |
char *bp, *buf; |
| 613 |
int i, slash_prefixed; |
| 614 |
struct filedesc *fdp; |
| 615 |
struct namecache *ncp; |
| 616 |
struct vnode *vp, *textvp; |
| 617 |
|
| 618 |
numfullpathcalls++; |
| 619 |
if (disablefullpath) |
| 620 |
return (ENODEV); |
| 621 |
textvp = p->p_textvp; |
| 622 |
if (textvp == NULL) |
| 623 |
return (EINVAL); |
| 624 |
buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); |
| 625 |
bp = buf + MAXPATHLEN - 1; |
| 626 |
*bp = '\0'; |
| 627 |
fdp = p->p_fd; |
| 628 |
slash_prefixed = 0; |
| 629 |
for (vp = textvp; vp != fdp->fd_rdir && vp != rootvnode;) { |
| 630 |
if (vp->v_flag & VROOT) { |
| 631 |
if (vp->v_mount == NULL) { /* forced unmount */ |
| 632 |
free(buf, M_TEMP); |
| 633 |
return (EBADF); |
| 634 |
} |
| 635 |
vp = vp->v_mount->mnt_vnodecovered; |
| 636 |
continue; |
| 637 |
} |
| 638 |
if (vp != textvp && vp->v_dd->v_id != vp->v_ddid) { |
| 639 |
numfullpathfail1++; |
| 640 |
free(buf, M_TEMP); |
| 641 |
return (ENOTDIR); |
| 642 |
} |
| 643 |
ncp = TAILQ_FIRST(&vp->v_cache_dst); |
| 644 |
if (!ncp) { |
| 645 |
numfullpathfail2++; |
| 646 |
free(buf, M_TEMP); |
| 647 |
return (ENOENT); |
| 648 |
} |
| 649 |
if (vp != textvp && ncp->nc_dvp != vp->v_dd) { |
| 650 |
numfullpathfail3++; |
| 651 |
free(buf, M_TEMP); |
| 652 |
return (EBADF); |
| 653 |
} |
| 654 |
for (i = ncp->nc_nlen - 1; i >= 0; i--) { |
| 655 |
if (bp == buf) { |
| 656 |
numfullpathfail4++; |
| 657 |
free(buf, M_TEMP); |
| 658 |
return (ENOMEM); |
| 659 |
} |
| 660 |
*--bp = ncp->nc_name[i]; |
| 661 |
} |
| 662 |
if (bp == buf) { |
| 663 |
numfullpathfail4++; |
| 664 |
free(buf, M_TEMP); |
| 665 |
return (ENOMEM); |
| 666 |
} |
| 667 |
*--bp = '/'; |
| 668 |
slash_prefixed = 1; |
| 669 |
vp = ncp->nc_dvp; |
| 670 |
} |
| 671 |
if (!slash_prefixed) { |
| 672 |
if (bp == buf) { |
| 673 |
numfullpathfail4++; |
| 674 |
free(buf, M_TEMP); |
| 675 |
return (ENOMEM); |
| 676 |
} |
| 677 |
*--bp = '/'; |
| 678 |
} |
| 679 |
numfullpathfound++; |
| 680 |
*retbuf = bp; |
| 681 |
*retfreebuf = buf; |
| 682 |
return (0); |
| 683 |
} |