1 /* $NetBSD: procfs_vnops.c,v 1.49 1997/05/08 16:20:22 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Jan-Simon Pendry 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)procfs_vnops.c 8.8 (Berkeley) 6/15/94 40 */ 41 42 /* 43 * procfs vnode interface 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/time.h> 49 #include <sys/kernel.h> 50 #include <sys/file.h> 51 #include <sys/proc.h> 52 #include <sys/vnode.h> 53 #include <sys/namei.h> 54 #include <sys/malloc.h> 55 #include <sys/dirent.h> 56 #include <sys/resourcevar.h> 57 #include <sys/ptrace.h> 58 #include <sys/stat.h> 59 60 #include <vm/vm.h> /* for PAGE_SIZE */ 61 62 #include <machine/reg.h> 63 64 #include <miscfs/genfs/genfs.h> 65 #include <miscfs/procfs/procfs.h> 66 67 /* 68 * Vnode Operations. 69 * 70 */ 71 72 /* 73 * This is a list of the valid names in the 74 * process-specific sub-directories. It is 75 * used in procfs_lookup and procfs_readdir 76 */ 77 struct proc_target { 78 u_char pt_type; 79 u_char pt_namlen; 80 char *pt_name; 81 pfstype pt_pfstype; 82 int (*pt_valid) __P((struct proc *p)); 83 } proc_targets[] = { 84 #define N(s) sizeof(s)-1, s 85 /* name type validp */ 86 { DT_DIR, N("."), Pproc, NULL }, 87 { DT_DIR, N(".."), Proot, NULL }, 88 { DT_REG, N("file"), Pfile, procfs_validfile }, 89 { DT_REG, N("mem"), Pmem, NULL }, 90 { DT_REG, N("regs"), Pregs, procfs_validregs }, 91 { DT_REG, N("fpregs"), Pfpregs, procfs_validfpregs }, 92 { DT_REG, N("ctl"), Pctl, NULL }, 93 { DT_REG, N("status"), Pstatus, NULL }, 94 { DT_REG, N("note"), Pnote, NULL }, 95 { DT_REG, N("notepg"), Pnotepg, NULL }, 96 #undef N 97 }; 98 static int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); 99 100 static pid_t atopid __P((const char *, u_int)); 101 102 int procfs_lookup __P((void *)); 103 #define procfs_create genfs_eopnotsupp 104 #define procfs_mknod genfs_eopnotsupp 105 int procfs_open __P((void *)); 106 int procfs_close __P((void *)); 107 int procfs_access __P((void *)); 108 int procfs_getattr __P((void *)); 109 int procfs_setattr __P((void *)); 110 #define procfs_read procfs_rw 111 #define procfs_write procfs_rw 112 #define procfs_ioctl genfs_eopnotsupp 113 #define procfs_poll genfs_poll 114 #define procfs_mmap genfs_eopnotsupp 115 #define procfs_fsync genfs_nullop 116 #define procfs_seek genfs_nullop 117 #define procfs_remove genfs_eopnotsupp 118 int procfs_link __P((void *)); 119 #define procfs_rename genfs_eopnotsupp 120 #define procfs_mkdir genfs_eopnotsupp 121 #define procfs_rmdir genfs_eopnotsupp 122 int procfs_symlink __P((void *)); 123 int procfs_readdir __P((void *)); 124 int procfs_readlink __P((void *)); 125 #define procfs_abortop genfs_abortop 126 int procfs_inactive __P((void *)); 127 int procfs_reclaim __P((void *)); 128 #define procfs_lock genfs_nullop 129 #define procfs_unlock genfs_nullop 130 int procfs_bmap __P((void *)); 131 #define procfs_strategy genfs_badop 132 int procfs_print __P((void *)); 133 int procfs_pathconf __P((void *)); 134 #define procfs_islocked genfs_nullop 135 #define procfs_advlock genfs_eopnotsupp 136 #define procfs_blkatoff genfs_eopnotsupp 137 #define procfs_valloc genfs_eopnotsupp 138 #define procfs_vfree genfs_nullop 139 #define procfs_truncate genfs_eopnotsupp 140 #define procfs_update genfs_nullop 141 #define procfs_bwrite genfs_eopnotsupp 142 143 static pid_t atopid __P((const char *, u_int)); 144 145 /* 146 * procfs vnode operations. 147 */ 148 int (**procfs_vnodeop_p) __P((void *)); 149 struct vnodeopv_entry_desc procfs_vnodeop_entries[] = { 150 { &vop_default_desc, vn_default_error }, 151 { &vop_lookup_desc, procfs_lookup }, /* lookup */ 152 { &vop_create_desc, procfs_create }, /* create */ 153 { &vop_mknod_desc, procfs_mknod }, /* mknod */ 154 { &vop_open_desc, procfs_open }, /* open */ 155 { &vop_close_desc, procfs_close }, /* close */ 156 { &vop_access_desc, procfs_access }, /* access */ 157 { &vop_getattr_desc, procfs_getattr }, /* getattr */ 158 { &vop_setattr_desc, procfs_setattr }, /* setattr */ 159 { &vop_read_desc, procfs_read }, /* read */ 160 { &vop_write_desc, procfs_write }, /* write */ 161 { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */ 162 { &vop_poll_desc, procfs_poll }, /* poll */ 163 { &vop_mmap_desc, procfs_mmap }, /* mmap */ 164 { &vop_fsync_desc, procfs_fsync }, /* fsync */ 165 { &vop_seek_desc, procfs_seek }, /* seek */ 166 { &vop_remove_desc, procfs_remove }, /* remove */ 167 { &vop_link_desc, procfs_link }, /* link */ 168 { &vop_rename_desc, procfs_rename }, /* rename */ 169 { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */ 170 { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */ 171 { &vop_symlink_desc, procfs_symlink }, /* symlink */ 172 { &vop_readdir_desc, procfs_readdir }, /* readdir */ 173 { &vop_readlink_desc, procfs_readlink }, /* readlink */ 174 { &vop_abortop_desc, procfs_abortop }, /* abortop */ 175 { &vop_inactive_desc, procfs_inactive }, /* inactive */ 176 { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */ 177 { &vop_lock_desc, procfs_lock }, /* lock */ 178 { &vop_unlock_desc, procfs_unlock }, /* unlock */ 179 { &vop_bmap_desc, procfs_bmap }, /* bmap */ 180 { &vop_strategy_desc, procfs_strategy }, /* strategy */ 181 { &vop_print_desc, procfs_print }, /* print */ 182 { &vop_islocked_desc, procfs_islocked }, /* islocked */ 183 { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */ 184 { &vop_advlock_desc, procfs_advlock }, /* advlock */ 185 { &vop_blkatoff_desc, procfs_blkatoff }, /* blkatoff */ 186 { &vop_valloc_desc, procfs_valloc }, /* valloc */ 187 { &vop_vfree_desc, procfs_vfree }, /* vfree */ 188 { &vop_truncate_desc, procfs_truncate }, /* truncate */ 189 { &vop_update_desc, procfs_update }, /* update */ 190 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } 191 }; 192 struct vnodeopv_desc procfs_vnodeop_opv_desc = 193 { &procfs_vnodeop_p, procfs_vnodeop_entries }; 194 /* 195 * set things up for doing i/o on 196 * the pfsnode (vp). (vp) is locked 197 * on entry, and should be left locked 198 * on exit. 199 * 200 * for procfs we don't need to do anything 201 * in particular for i/o. all that is done 202 * is to support exclusive open on process 203 * memory images. 204 */ 205 int 206 procfs_open(v) 207 void *v; 208 { 209 struct vop_open_args /* { 210 struct vnode *a_vp; 211 int a_mode; 212 struct ucred *a_cred; 213 struct proc *a_p; 214 } */ *ap = v; 215 struct pfsnode *pfs = VTOPFS(ap->a_vp); 216 217 switch (pfs->pfs_type) { 218 case Pmem: 219 if (PFIND(pfs->pfs_pid) == 0) 220 return (ENOENT); /* was ESRCH, jsp */ 221 222 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || 223 ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) 224 return (EBUSY); 225 226 if (ap->a_mode & FWRITE) 227 pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); 228 229 return (0); 230 231 default: 232 break; 233 } 234 235 return (0); 236 } 237 238 /* 239 * close the pfsnode (vp) after doing i/o. 240 * (vp) is not locked on entry or exit. 241 * 242 * nothing to do for procfs other than undo 243 * any exclusive open flag (see _open above). 244 */ 245 int 246 procfs_close(v) 247 void *v; 248 { 249 struct vop_close_args /* { 250 struct vnode *a_vp; 251 int a_fflag; 252 struct ucred *a_cred; 253 struct proc *a_p; 254 } */ *ap = v; 255 struct pfsnode *pfs = VTOPFS(ap->a_vp); 256 257 switch (pfs->pfs_type) { 258 case Pmem: 259 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) 260 pfs->pfs_flags &= ~(FWRITE|O_EXCL); 261 break; 262 263 default: 264 break; 265 } 266 267 return (0); 268 } 269 270 /* 271 * do block mapping for pfsnode (vp). 272 * since we don't use the buffer cache 273 * for procfs this function should never 274 * be called. in any case, it's not clear 275 * what part of the kernel ever makes use 276 * of this function. for sanity, this is the 277 * usual no-op bmap, although returning 278 * (EIO) would be a reasonable alternative. 279 */ 280 int 281 procfs_bmap(v) 282 void *v; 283 { 284 struct vop_bmap_args /* { 285 struct vnode *a_vp; 286 daddr_t a_bn; 287 struct vnode **a_vpp; 288 daddr_t *a_bnp; 289 } */ *ap = v; 290 291 if (ap->a_vpp != NULL) 292 *ap->a_vpp = ap->a_vp; 293 if (ap->a_bnp != NULL) 294 *ap->a_bnp = ap->a_bn; 295 return (0); 296 } 297 298 /* 299 * _inactive is called when the pfsnode 300 * is vrele'd and the reference count goes 301 * to zero. (vp) will be on the vnode free 302 * list, so to get it back vget() must be 303 * used. 304 * 305 * for procfs, check if the process is still 306 * alive and if it isn't then just throw away 307 * the vnode by calling vgone(). this may 308 * be overkill and a waste of time since the 309 * chances are that the process will still be 310 * there and PFIND is not free. 311 * 312 * (vp) is not locked on entry or exit. 313 */ 314 int 315 procfs_inactive(v) 316 void *v; 317 { 318 struct vop_inactive_args /* { 319 struct vnode *a_vp; 320 } */ *ap = v; 321 struct pfsnode *pfs = VTOPFS(ap->a_vp); 322 323 if (PFIND(pfs->pfs_pid) == 0) 324 vgone(ap->a_vp); 325 326 return (0); 327 } 328 329 /* 330 * _reclaim is called when getnewvnode() 331 * wants to make use of an entry on the vnode 332 * free list. at this time the filesystem needs 333 * to free any private data and remove the node 334 * from any private lists. 335 */ 336 int 337 procfs_reclaim(v) 338 void *v; 339 { 340 struct vop_reclaim_args /* { 341 struct vnode *a_vp; 342 } */ *ap = v; 343 344 return (procfs_freevp(ap->a_vp)); 345 } 346 347 /* 348 * Return POSIX pathconf information applicable to special devices. 349 */ 350 int 351 procfs_pathconf(v) 352 void *v; 353 { 354 struct vop_pathconf_args /* { 355 struct vnode *a_vp; 356 int a_name; 357 register_t *a_retval; 358 } */ *ap = v; 359 360 switch (ap->a_name) { 361 case _PC_LINK_MAX: 362 *ap->a_retval = LINK_MAX; 363 return (0); 364 case _PC_MAX_CANON: 365 *ap->a_retval = MAX_CANON; 366 return (0); 367 case _PC_MAX_INPUT: 368 *ap->a_retval = MAX_INPUT; 369 return (0); 370 case _PC_PIPE_BUF: 371 *ap->a_retval = PIPE_BUF; 372 return (0); 373 case _PC_CHOWN_RESTRICTED: 374 *ap->a_retval = 1; 375 return (0); 376 case _PC_VDISABLE: 377 *ap->a_retval = _POSIX_VDISABLE; 378 return (0); 379 default: 380 return (EINVAL); 381 } 382 /* NOTREACHED */ 383 } 384 385 /* 386 * _print is used for debugging. 387 * just print a readable description 388 * of (vp). 389 */ 390 int 391 procfs_print(v) 392 void *v; 393 { 394 struct vop_print_args /* { 395 struct vnode *a_vp; 396 } */ *ap = v; 397 struct pfsnode *pfs = VTOPFS(ap->a_vp); 398 399 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n", 400 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); 401 return 0; 402 } 403 404 int 405 procfs_link(v) 406 void *v; 407 { 408 struct vop_link_args /* { 409 struct vnode *a_dvp; 410 struct vnode *a_vp; 411 struct componentname *a_cnp; 412 } */ *ap = v; 413 414 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 415 vput(ap->a_dvp); 416 return (EROFS); 417 } 418 419 int 420 procfs_symlink(v) 421 void *v; 422 { 423 struct vop_symlink_args /* { 424 struct vnode *a_dvp; 425 struct vnode **a_vpp; 426 struct componentname *a_cnp; 427 struct vattr *a_vap; 428 char *a_target; 429 } */ *ap = v; 430 431 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 432 vput(ap->a_dvp); 433 return (EROFS); 434 } 435 436 /* 437 * Invent attributes for pfsnode (vp) and store 438 * them in (vap). 439 * Directories lengths are returned as zero since 440 * any real length would require the genuine size 441 * to be computed, and nothing cares anyway. 442 * 443 * this is relatively minimal for procfs. 444 */ 445 int 446 procfs_getattr(v) 447 void *v; 448 { 449 struct vop_getattr_args /* { 450 struct vnode *a_vp; 451 struct vattr *a_vap; 452 struct ucred *a_cred; 453 struct proc *a_p; 454 } */ *ap = v; 455 struct pfsnode *pfs = VTOPFS(ap->a_vp); 456 struct vattr *vap = ap->a_vap; 457 struct proc *procp; 458 struct timeval tv; 459 int error; 460 461 /* first check the process still exists */ 462 switch (pfs->pfs_type) { 463 case Proot: 464 case Pcurproc: 465 procp = 0; 466 break; 467 468 default: 469 procp = PFIND(pfs->pfs_pid); 470 if (procp == 0) 471 return (ENOENT); 472 break; 473 } 474 475 error = 0; 476 477 /* start by zeroing out the attributes */ 478 VATTR_NULL(vap); 479 480 /* next do all the common fields */ 481 vap->va_type = ap->a_vp->v_type; 482 vap->va_mode = pfs->pfs_mode; 483 vap->va_fileid = pfs->pfs_fileno; 484 vap->va_flags = 0; 485 vap->va_blocksize = PAGE_SIZE; 486 487 /* 488 * Make all times be current TOD. 489 * It would be possible to get the process start 490 * time from the p_stat structure, but there's 491 * no "file creation" time stamp anyway, and the 492 * p_stat structure is not addressible if u. gets 493 * swapped out for that process. 494 */ 495 microtime(&tv); 496 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime); 497 vap->va_atime = vap->va_mtime = vap->va_ctime; 498 499 switch (pfs->pfs_type) { 500 case Pmem: 501 case Pregs: 502 case Pfpregs: 503 /* 504 * If the process has exercised some setuid or setgid 505 * privilege, then rip away read/write permission so 506 * that only root can gain access. 507 */ 508 if (procp->p_flag & P_SUGID) 509 vap->va_mode &= ~(S_IRUSR|S_IWUSR); 510 /* FALLTHROUGH */ 511 case Pctl: 512 case Pstatus: 513 case Pnote: 514 case Pnotepg: 515 vap->va_nlink = 1; 516 vap->va_uid = procp->p_ucred->cr_uid; 517 vap->va_gid = procp->p_ucred->cr_gid; 518 break; 519 520 default: 521 break; 522 } 523 524 /* 525 * now do the object specific fields 526 * 527 * The size could be set from struct reg, but it's hardly 528 * worth the trouble, and it puts some (potentially) machine 529 * dependent data into this machine-independent code. If it 530 * becomes important then this function should break out into 531 * a per-file stat function in the corresponding .c file. 532 */ 533 534 switch (pfs->pfs_type) { 535 case Proot: 536 /* 537 * Set nlink to 1 to tell fts(3) we don't actually know. 538 */ 539 vap->va_nlink = 1; 540 vap->va_uid = 0; 541 vap->va_gid = 0; 542 vap->va_bytes = vap->va_size = DEV_BSIZE; 543 break; 544 545 case Pcurproc: { 546 char buf[16]; /* should be enough */ 547 vap->va_nlink = 1; 548 vap->va_uid = 0; 549 vap->va_gid = 0; 550 vap->va_bytes = vap->va_size = 551 sprintf(buf, "%ld", (long)curproc->p_pid); 552 break; 553 } 554 555 case Pproc: 556 vap->va_nlink = 2; 557 vap->va_uid = procp->p_ucred->cr_uid; 558 vap->va_gid = procp->p_ucred->cr_gid; 559 vap->va_bytes = vap->va_size = DEV_BSIZE; 560 break; 561 562 case Pfile: 563 error = EOPNOTSUPP; 564 break; 565 566 case Pmem: 567 vap->va_bytes = vap->va_size = 568 ctob(procp->p_vmspace->vm_tsize + 569 procp->p_vmspace->vm_dsize + 570 procp->p_vmspace->vm_ssize); 571 break; 572 573 #if defined(PT_GETREGS) || defined(PT_SETREGS) 574 case Pregs: 575 vap->va_bytes = vap->va_size = sizeof(struct reg); 576 break; 577 #endif 578 579 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) 580 case Pfpregs: 581 vap->va_bytes = vap->va_size = sizeof(struct fpreg); 582 break; 583 #endif 584 585 case Pctl: 586 case Pstatus: 587 case Pnote: 588 case Pnotepg: 589 vap->va_bytes = vap->va_size = 0; 590 break; 591 592 default: 593 panic("procfs_getattr"); 594 } 595 596 return (error); 597 } 598 599 /*ARGSUSED*/ 600 int 601 procfs_setattr(v) 602 void *v; 603 { 604 /* 605 * just fake out attribute setting 606 * it's not good to generate an error 607 * return, otherwise things like creat() 608 * will fail when they try to set the 609 * file length to 0. worse, this means 610 * that echo $note > /proc/$pid/note will fail. 611 */ 612 613 return (0); 614 } 615 616 /* 617 * implement access checking. 618 * 619 * actually, the check for super-user is slightly 620 * broken since it will allow read access to write-only 621 * objects. this doesn't cause any particular trouble 622 * but does mean that the i/o entry points need to check 623 * that the operation really does make sense. 624 */ 625 int 626 procfs_access(v) 627 void *v; 628 { 629 struct vop_access_args /* { 630 struct vnode *a_vp; 631 int a_mode; 632 struct ucred *a_cred; 633 struct proc *a_p; 634 } */ *ap = v; 635 struct vattr va; 636 int error; 637 638 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) 639 return (error); 640 641 return (vaccess(va.va_type, va.va_mode, 642 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 643 } 644 645 /* 646 * lookup. this is incredibly complicated in the 647 * general case, however for most pseudo-filesystems 648 * very little needs to be done. 649 * 650 * unless you want to get a migraine, just make sure your 651 * filesystem doesn't do any locking of its own. otherwise 652 * read and inwardly digest ufs_lookup(). 653 */ 654 int 655 procfs_lookup(v) 656 void *v; 657 { 658 struct vop_lookup_args /* { 659 struct vnode * a_dvp; 660 struct vnode ** a_vpp; 661 struct componentname * a_cnp; 662 } */ *ap = v; 663 struct componentname *cnp = ap->a_cnp; 664 struct vnode **vpp = ap->a_vpp; 665 struct vnode *dvp = ap->a_dvp; 666 const char *pname = cnp->cn_nameptr; 667 struct proc_target *pt; 668 struct vnode *fvp; 669 pid_t pid; 670 struct pfsnode *pfs; 671 struct proc *p; 672 int i; 673 674 *vpp = NULL; 675 676 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 677 return (EROFS); 678 679 if (cnp->cn_namelen == 1 && *pname == '.') { 680 *vpp = dvp; 681 VREF(dvp); 682 /*VOP_LOCK(dvp);*/ 683 return (0); 684 } 685 686 pfs = VTOPFS(dvp); 687 switch (pfs->pfs_type) { 688 case Proot: 689 if (cnp->cn_flags & ISDOTDOT) 690 return (EIO); 691 692 if (CNEQ(cnp, "curproc", 7)) 693 return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc)); 694 695 pid = atopid(pname, cnp->cn_namelen); 696 if (pid == NO_PID) 697 break; 698 699 p = PFIND(pid); 700 if (p == 0) 701 break; 702 703 return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc)); 704 705 case Pproc: 706 if (cnp->cn_flags & ISDOTDOT) 707 return (procfs_root(dvp->v_mount, vpp)); 708 709 p = PFIND(pfs->pfs_pid); 710 if (p == 0) 711 break; 712 713 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { 714 if (cnp->cn_namelen == pt->pt_namlen && 715 bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 716 (pt->pt_valid == NULL || (*pt->pt_valid)(p))) 717 goto found; 718 } 719 break; 720 721 found: 722 if (pt->pt_pfstype == Pfile) { 723 fvp = procfs_findtextvp(p); 724 /* We already checked that it exists. */ 725 VREF(fvp); 726 VOP_LOCK(fvp); 727 *vpp = fvp; 728 return (0); 729 } 730 731 return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 732 pt->pt_pfstype)); 733 734 default: 735 return (ENOTDIR); 736 } 737 738 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 739 } 740 741 int 742 procfs_validfile(p) 743 struct proc *p; 744 { 745 746 return (procfs_findtextvp(p) != NULLVP); 747 } 748 749 /* 750 * readdir returns directory entries from pfsnode (vp). 751 * 752 * the strategy here with procfs is to generate a single 753 * directory entry at a time (struct dirent) and then 754 * copy that out to userland using uiomove. a more efficent 755 * though more complex implementation, would try to minimize 756 * the number of calls to uiomove(). for procfs, this is 757 * hardly worth the added code complexity. 758 * 759 * this should just be done through read() 760 */ 761 int 762 procfs_readdir(v) 763 void *v; 764 { 765 struct vop_readdir_args /* { 766 struct vnode *a_vp; 767 struct uio *a_uio; 768 struct ucred *a_cred; 769 int *a_eofflag; 770 u_long *a_cookies; 771 int a_ncookies; 772 } */ *ap = v; 773 struct uio *uio = ap->a_uio; 774 struct dirent d; 775 struct pfsnode *pfs; 776 int i; 777 int error; 778 u_long *cookies = ap->a_cookies; 779 int ncookies = ap->a_ncookies; 780 781 pfs = VTOPFS(ap->a_vp); 782 783 if (uio->uio_resid < UIO_MX) 784 return (EINVAL); 785 if (uio->uio_offset < 0) 786 return (EINVAL); 787 788 error = 0; 789 i = uio->uio_offset; 790 bzero((caddr_t)&d, UIO_MX); 791 d.d_reclen = UIO_MX; 792 793 switch (pfs->pfs_type) { 794 /* 795 * this is for the process-specific sub-directories. 796 * all that is needed to is copy out all the entries 797 * from the procent[] table (top of this file). 798 */ 799 case Pproc: { 800 struct proc *p; 801 struct proc_target *pt; 802 803 p = PFIND(pfs->pfs_pid); 804 if (p == NULL) 805 break; 806 807 for (pt = &proc_targets[i]; 808 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { 809 if (pt->pt_valid && (*pt->pt_valid)(p) == 0) 810 continue; 811 812 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype); 813 d.d_namlen = pt->pt_namlen; 814 bcopy(pt->pt_name, d.d_name, pt->pt_namlen + 1); 815 d.d_type = pt->pt_type; 816 817 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 818 break; 819 if (ncookies-- > 0) 820 *cookies++ = i + 1; 821 } 822 823 break; 824 } 825 826 /* 827 * this is for the root of the procfs filesystem 828 * what is needed is a special entry for "curproc" 829 * followed by an entry for each process on allproc 830 #ifdef PROCFS_ZOMBIE 831 * and zombproc. 832 #endif 833 */ 834 835 case Proot: { 836 #ifdef PROCFS_ZOMBIE 837 int doingzomb = 0; 838 #endif 839 int pcnt = i; 840 volatile struct proc *p = allproc.lh_first; 841 842 if (pcnt > 3) 843 pcnt = 3; 844 #ifdef PROCFS_ZOMBIE 845 again: 846 #endif 847 for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) { 848 switch (i) { 849 case 0: /* `.' */ 850 case 1: /* `..' */ 851 d.d_fileno = PROCFS_FILENO(0, Proot); 852 d.d_namlen = i + 1; 853 bcopy("..", d.d_name, d.d_namlen); 854 d.d_name[i + 1] = '\0'; 855 d.d_type = DT_DIR; 856 break; 857 858 case 2: 859 d.d_fileno = PROCFS_FILENO(0, Pcurproc); 860 d.d_namlen = 7; 861 bcopy("curproc", d.d_name, 8); 862 d.d_type = DT_LNK; 863 break; 864 865 default: 866 while (pcnt < i) { 867 pcnt++; 868 p = p->p_list.le_next; 869 if (!p) 870 goto done; 871 } 872 d.d_fileno = PROCFS_FILENO(p->p_pid, Pproc); 873 d.d_namlen = sprintf(d.d_name, "%ld", 874 (long)p->p_pid); 875 d.d_type = DT_REG; 876 p = p->p_list.le_next; 877 break; 878 } 879 880 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 881 break; 882 if (ncookies-- > 0) 883 *cookies++ = i + 1; 884 } 885 done: 886 887 #ifdef PROCFS_ZOMBIE 888 if (p == 0 && doingzomb == 0) { 889 doingzomb = 1; 890 p = zombproc.lh_first; 891 goto again; 892 } 893 #endif 894 895 break; 896 897 } 898 899 default: 900 error = ENOTDIR; 901 break; 902 } 903 904 uio->uio_offset = i; 905 return (error); 906 } 907 908 /* 909 * readlink reads the link of `curproc' 910 */ 911 int 912 procfs_readlink(v) 913 void *v; 914 { 915 struct vop_readlink_args *ap = v; 916 char buf[16]; /* should be enough */ 917 int len; 918 919 if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc)) 920 return (EINVAL); 921 922 len = sprintf(buf, "%ld", (long)curproc->p_pid); 923 924 return (uiomove((caddr_t)buf, len, ap->a_uio)); 925 } 926 927 /* 928 * convert decimal ascii to pid_t 929 */ 930 static pid_t 931 atopid(b, len) 932 const char *b; 933 u_int len; 934 { 935 pid_t p = 0; 936 937 while (len--) { 938 char c = *b++; 939 if (c < '0' || c > '9') 940 return (NO_PID); 941 p = 10 * p + (c - '0'); 942 if (p > PID_MAX) 943 return (NO_PID); 944 } 945 946 return (p); 947 } 948