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