1 /* $NetBSD: procfs_vnops.c,v 1.59 1998/09/08 23:50:14 thorpej 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_enoioctl 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_einval 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 case _PC_SYNC_IO: 395 *ap->a_retval = 1; 396 return (0); 397 default: 398 return (EINVAL); 399 } 400 /* NOTREACHED */ 401 } 402 403 /* 404 * _print is used for debugging. 405 * just print a readable description 406 * of (vp). 407 */ 408 int 409 procfs_print(v) 410 void *v; 411 { 412 struct vop_print_args /* { 413 struct vnode *a_vp; 414 } */ *ap = v; 415 struct pfsnode *pfs = VTOPFS(ap->a_vp); 416 417 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n", 418 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); 419 return 0; 420 } 421 422 int 423 procfs_link(v) 424 void *v; 425 { 426 struct vop_link_args /* { 427 struct vnode *a_dvp; 428 struct vnode *a_vp; 429 struct componentname *a_cnp; 430 } */ *ap = v; 431 432 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 433 vput(ap->a_dvp); 434 return (EROFS); 435 } 436 437 int 438 procfs_symlink(v) 439 void *v; 440 { 441 struct vop_symlink_args /* { 442 struct vnode *a_dvp; 443 struct vnode **a_vpp; 444 struct componentname *a_cnp; 445 struct vattr *a_vap; 446 char *a_target; 447 } */ *ap = v; 448 449 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 450 vput(ap->a_dvp); 451 return (EROFS); 452 } 453 454 /* 455 * Invent attributes for pfsnode (vp) and store 456 * them in (vap). 457 * Directories lengths are returned as zero since 458 * any real length would require the genuine size 459 * to be computed, and nothing cares anyway. 460 * 461 * this is relatively minimal for procfs. 462 */ 463 int 464 procfs_getattr(v) 465 void *v; 466 { 467 struct vop_getattr_args /* { 468 struct vnode *a_vp; 469 struct vattr *a_vap; 470 struct ucred *a_cred; 471 struct proc *a_p; 472 } */ *ap = v; 473 struct pfsnode *pfs = VTOPFS(ap->a_vp); 474 struct vattr *vap = ap->a_vap; 475 struct proc *procp; 476 struct timeval tv; 477 int error; 478 479 /* first check the process still exists */ 480 switch (pfs->pfs_type) { 481 case Proot: 482 case Pcurproc: 483 procp = 0; 484 break; 485 486 default: 487 procp = PFIND(pfs->pfs_pid); 488 if (procp == 0) 489 return (ENOENT); 490 break; 491 } 492 493 error = 0; 494 495 /* start by zeroing out the attributes */ 496 VATTR_NULL(vap); 497 498 /* next do all the common fields */ 499 vap->va_type = ap->a_vp->v_type; 500 vap->va_mode = pfs->pfs_mode; 501 vap->va_fileid = pfs->pfs_fileno; 502 vap->va_flags = 0; 503 vap->va_blocksize = PAGE_SIZE; 504 505 /* 506 * Make all times be current TOD. 507 * It would be possible to get the process start 508 * time from the p_stat structure, but there's 509 * no "file creation" time stamp anyway, and the 510 * p_stat structure is not addressible if u. gets 511 * swapped out for that process. 512 */ 513 microtime(&tv); 514 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime); 515 vap->va_atime = vap->va_mtime = vap->va_ctime; 516 517 switch (pfs->pfs_type) { 518 case Pmem: 519 case Pregs: 520 case Pfpregs: 521 /* 522 * If the process has exercised some setuid or setgid 523 * privilege, then rip away read/write permission so 524 * that only root can gain access. 525 */ 526 if (procp->p_flag & P_SUGID) 527 vap->va_mode &= ~(S_IRUSR|S_IWUSR); 528 /* FALLTHROUGH */ 529 case Pctl: 530 case Pstatus: 531 case Pnote: 532 case Pnotepg: 533 vap->va_nlink = 1; 534 vap->va_uid = procp->p_ucred->cr_uid; 535 vap->va_gid = procp->p_ucred->cr_gid; 536 break; 537 538 default: 539 break; 540 } 541 542 /* 543 * now do the object specific fields 544 * 545 * The size could be set from struct reg, but it's hardly 546 * worth the trouble, and it puts some (potentially) machine 547 * dependent data into this machine-independent code. If it 548 * becomes important then this function should break out into 549 * a per-file stat function in the corresponding .c file. 550 */ 551 552 switch (pfs->pfs_type) { 553 case Proot: 554 /* 555 * Set nlink to 1 to tell fts(3) we don't actually know. 556 */ 557 vap->va_nlink = 1; 558 vap->va_uid = 0; 559 vap->va_gid = 0; 560 vap->va_bytes = vap->va_size = DEV_BSIZE; 561 break; 562 563 case Pcurproc: { 564 char buf[16]; /* should be enough */ 565 vap->va_nlink = 1; 566 vap->va_uid = 0; 567 vap->va_gid = 0; 568 vap->va_bytes = vap->va_size = 569 sprintf(buf, "%ld", (long)curproc->p_pid); 570 break; 571 } 572 573 case Pproc: 574 vap->va_nlink = 2; 575 vap->va_uid = procp->p_ucred->cr_uid; 576 vap->va_gid = procp->p_ucred->cr_gid; 577 vap->va_bytes = vap->va_size = DEV_BSIZE; 578 break; 579 580 case Pfile: 581 error = EOPNOTSUPP; 582 break; 583 584 case Pmem: 585 vap->va_bytes = vap->va_size = 586 ctob(procp->p_vmspace->vm_tsize + 587 procp->p_vmspace->vm_dsize + 588 procp->p_vmspace->vm_ssize); 589 break; 590 591 #if defined(PT_GETREGS) || defined(PT_SETREGS) 592 case Pregs: 593 vap->va_bytes = vap->va_size = sizeof(struct reg); 594 break; 595 #endif 596 597 #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) 598 case Pfpregs: 599 vap->va_bytes = vap->va_size = sizeof(struct fpreg); 600 break; 601 #endif 602 603 case Pctl: 604 case Pstatus: 605 case Pnote: 606 case Pnotepg: 607 vap->va_bytes = vap->va_size = 0; 608 break; 609 610 default: 611 panic("procfs_getattr"); 612 } 613 614 return (error); 615 } 616 617 /*ARGSUSED*/ 618 int 619 procfs_setattr(v) 620 void *v; 621 { 622 /* 623 * just fake out attribute setting 624 * it's not good to generate an error 625 * return, otherwise things like creat() 626 * will fail when they try to set the 627 * file length to 0. worse, this means 628 * that echo $note > /proc/$pid/note will fail. 629 */ 630 631 return (0); 632 } 633 634 /* 635 * implement access checking. 636 * 637 * actually, the check for super-user is slightly 638 * broken since it will allow read access to write-only 639 * objects. this doesn't cause any particular trouble 640 * but does mean that the i/o entry points need to check 641 * that the operation really does make sense. 642 */ 643 int 644 procfs_access(v) 645 void *v; 646 { 647 struct vop_access_args /* { 648 struct vnode *a_vp; 649 int a_mode; 650 struct ucred *a_cred; 651 struct proc *a_p; 652 } */ *ap = v; 653 struct vattr va; 654 int error; 655 656 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) 657 return (error); 658 659 return (vaccess(va.va_type, va.va_mode, 660 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 661 } 662 663 /* 664 * lookup. this is incredibly complicated in the 665 * general case, however for most pseudo-filesystems 666 * very little needs to be done. 667 * 668 * unless you want to get a migraine, just make sure your 669 * filesystem doesn't do any locking of its own. otherwise 670 * read and inwardly digest ufs_lookup(). 671 */ 672 int 673 procfs_lookup(v) 674 void *v; 675 { 676 struct vop_lookup_args /* { 677 struct vnode * a_dvp; 678 struct vnode ** a_vpp; 679 struct componentname * a_cnp; 680 } */ *ap = v; 681 struct componentname *cnp = ap->a_cnp; 682 struct vnode **vpp = ap->a_vpp; 683 struct vnode *dvp = ap->a_dvp; 684 const char *pname = cnp->cn_nameptr; 685 struct proc_target *pt; 686 struct vnode *fvp; 687 pid_t pid; 688 struct pfsnode *pfs; 689 struct proc *p; 690 int i; 691 692 *vpp = NULL; 693 694 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 695 return (EROFS); 696 697 if (cnp->cn_namelen == 1 && *pname == '.') { 698 *vpp = dvp; 699 VREF(dvp); 700 /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */ 701 return (0); 702 } 703 704 pfs = VTOPFS(dvp); 705 switch (pfs->pfs_type) { 706 case Proot: 707 if (cnp->cn_flags & ISDOTDOT) 708 return (EIO); 709 710 if (CNEQ(cnp, "curproc", 7)) 711 return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc)); 712 713 pid = atopid(pname, cnp->cn_namelen); 714 if (pid == NO_PID) 715 break; 716 717 p = PFIND(pid); 718 if (p == 0) 719 break; 720 721 return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc)); 722 723 case Pproc: 724 if (cnp->cn_flags & ISDOTDOT) 725 return (procfs_root(dvp->v_mount, vpp)); 726 727 p = PFIND(pfs->pfs_pid); 728 if (p == 0) 729 break; 730 731 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { 732 if (cnp->cn_namelen == pt->pt_namlen && 733 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 734 (pt->pt_valid == NULL || (*pt->pt_valid)(p))) 735 goto found; 736 } 737 break; 738 739 found: 740 if (pt->pt_pfstype == Pfile) { 741 fvp = procfs_findtextvp(p); 742 /* We already checked that it exists. */ 743 VREF(fvp); 744 vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY); 745 *vpp = fvp; 746 return (0); 747 } 748 749 return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 750 pt->pt_pfstype)); 751 752 default: 753 return (ENOTDIR); 754 } 755 756 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 757 } 758 759 int 760 procfs_validfile(p) 761 struct proc *p; 762 { 763 764 return (procfs_findtextvp(p) != NULLVP); 765 } 766 767 /* 768 * readdir returns directory entries from pfsnode (vp). 769 * 770 * the strategy here with procfs is to generate a single 771 * directory entry at a time (struct dirent) and then 772 * copy that out to userland using uiomove. a more efficent 773 * though more complex implementation, would try to minimize 774 * the number of calls to uiomove(). for procfs, this is 775 * hardly worth the added code complexity. 776 * 777 * this should just be done through read() 778 */ 779 int 780 procfs_readdir(v) 781 void *v; 782 { 783 struct vop_readdir_args /* { 784 struct vnode *a_vp; 785 struct uio *a_uio; 786 struct ucred *a_cred; 787 int *a_eofflag; 788 off_t **a_cookies; 789 int *a_ncookies; 790 } */ *ap = v; 791 struct uio *uio = ap->a_uio; 792 struct dirent d; 793 struct pfsnode *pfs; 794 int i; 795 int error; 796 off_t *cookies = NULL; 797 int ncookies; 798 799 pfs = VTOPFS(ap->a_vp); 800 801 if (uio->uio_resid < UIO_MX) 802 return (EINVAL); 803 if (uio->uio_offset < 0) 804 return (EINVAL); 805 806 error = 0; 807 i = uio->uio_offset; 808 memset((caddr_t)&d, 0, UIO_MX); 809 d.d_reclen = UIO_MX; 810 ncookies = uio->uio_resid / UIO_MX; 811 812 switch (pfs->pfs_type) { 813 /* 814 * this is for the process-specific sub-directories. 815 * all that is needed to is copy out all the entries 816 * from the procent[] table (top of this file). 817 */ 818 case Pproc: { 819 struct proc *p; 820 struct proc_target *pt; 821 822 p = PFIND(pfs->pfs_pid); 823 if (p == NULL) 824 break; 825 826 if (ap->a_ncookies) { 827 ncookies = min(ncookies, (nproc_targets - i)); 828 MALLOC(cookies, off_t *, ncookies * sizeof (off_t), 829 M_TEMP, M_WAITOK); 830 *ap->a_cookies = cookies; 831 } 832 833 for (pt = &proc_targets[i]; 834 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { 835 if (pt->pt_valid && (*pt->pt_valid)(p) == 0) 836 continue; 837 838 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype); 839 d.d_namlen = pt->pt_namlen; 840 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 841 d.d_type = pt->pt_type; 842 843 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 844 break; 845 if (cookies) 846 *cookies++ = i + 1; 847 } 848 849 break; 850 } 851 852 /* 853 * this is for the root of the procfs filesystem 854 * what is needed is a special entry for "curproc" 855 * followed by an entry for each process on allproc 856 #ifdef PROCFS_ZOMBIE 857 * and deadproc and zombproc. 858 #endif 859 */ 860 861 case Proot: { 862 int pcnt = i, nc = 0; 863 const struct proclist_desc *pd; 864 volatile struct proc *p; 865 866 if (pcnt > 3) 867 pcnt = 3; 868 if (ap->a_ncookies) { 869 /* 870 * XXX Potentially allocating too much space here, 871 * but I'm lazy. This loop needs some work. 872 */ 873 MALLOC(cookies, off_t *, ncookies * sizeof (off_t), 874 M_TEMP, M_WAITOK); 875 *ap->a_cookies = cookies; 876 } 877 /* 878 * XXX: THIS LOOP ASSUMES THAT allproc IS THE FIRST 879 * PROCLIST IN THE proclists! 880 */ 881 pd = proclists; 882 #ifdef PROCFS_ZOMBIE 883 again: 884 #endif 885 for (p = LIST_FIRST(pd->pd_list); 886 p != NULL && uio->uio_resid >= UIO_MX; i++, pcnt++) { 887 switch (i) { 888 case 0: /* `.' */ 889 case 1: /* `..' */ 890 d.d_fileno = PROCFS_FILENO(0, Proot); 891 d.d_namlen = i + 1; 892 memcpy(d.d_name, "..", d.d_namlen); 893 d.d_name[i + 1] = '\0'; 894 d.d_type = DT_DIR; 895 break; 896 897 case 2: 898 d.d_fileno = PROCFS_FILENO(0, Pcurproc); 899 d.d_namlen = 7; 900 memcpy(d.d_name, "curproc", 8); 901 d.d_type = DT_LNK; 902 break; 903 904 default: 905 while (pcnt < i) { 906 pcnt++; 907 p = LIST_NEXT(p, p_list); 908 if (!p) 909 goto done; 910 } 911 d.d_fileno = PROCFS_FILENO(p->p_pid, Pproc); 912 d.d_namlen = sprintf(d.d_name, "%ld", 913 (long)p->p_pid); 914 d.d_type = DT_REG; 915 p = p->p_list.le_next; 916 break; 917 } 918 919 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 920 break; 921 nc++; 922 if (cookies) 923 *cookies++ = i + 1; 924 } 925 done: 926 927 #ifdef PROCFS_ZOMBIE 928 pd++; 929 if (p == NULL && pd->pd_list != NULL) 930 goto again; 931 #endif 932 ncookies = nc; 933 934 break; 935 936 } 937 938 default: 939 error = ENOTDIR; 940 break; 941 } 942 943 if (ap->a_ncookies) { 944 if (error) { 945 if (cookies) 946 FREE(*ap->a_cookies, M_TEMP); 947 *ap->a_ncookies = 0; 948 *ap->a_cookies = NULL; 949 } else 950 *ap->a_ncookies = ncookies; 951 } 952 uio->uio_offset = i; 953 return (error); 954 } 955 956 /* 957 * readlink reads the link of `curproc' 958 */ 959 int 960 procfs_readlink(v) 961 void *v; 962 { 963 struct vop_readlink_args *ap = v; 964 char buf[16]; /* should be enough */ 965 int len; 966 967 if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc)) 968 return (EINVAL); 969 970 len = sprintf(buf, "%ld", (long)curproc->p_pid); 971 972 return (uiomove((caddr_t)buf, len, ap->a_uio)); 973 } 974 975 /* 976 * convert decimal ascii to pid_t 977 */ 978 static pid_t 979 atopid(b, len) 980 const char *b; 981 u_int len; 982 { 983 pid_t p = 0; 984 985 while (len--) { 986 char c = *b++; 987 if (c < '0' || c > '9') 988 return (NO_PID); 989 p = 10 * p + (c - '0'); 990 if (p > PID_MAX) 991 return (NO_PID); 992 } 993 994 return (p); 995 } 996