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