1 /* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 29 /* 30 * Copyright (c) 1992, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software donated to Berkeley by 34 * Jan-Simon Pendry. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95 65 * 66 */ 67 68 /* 69 * /dev/fd Filesystem 70 */ 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/types.h> 75 #include <sys/time.h> 76 #include <sys/proc_internal.h> 77 #include <sys/kernel.h> /* boottime */ 78 #include <sys/resourcevar.h> 79 #include <sys/filedesc.h> 80 #include <sys/kauth.h> 81 #include <sys/vnode_internal.h> 82 #include <sys/malloc.h> 83 #include <sys/file_internal.h> 84 #include <sys/stat.h> 85 #include <sys/mount_internal.h> 86 #include <sys/namei.h> 87 #include <sys/dirent.h> 88 #include <sys/ubc.h> 89 #include <sys/socketvar.h> 90 #include <sys/pipe.h> 91 #include <sys/uio_internal.h> 92 #include <vfs/vfs_support.h> 93 #include <pexpert/pexpert.h> 94 #include <miscfs/devfs/fdesc.h> 95 #include <miscfs/devfs/devfs.h> 96 #include <miscfs/devfs/devfsdefs.h> 97 98 /* XXX should be prototyped in header for here, kern_descrip.c */ 99 extern int soo_stat(struct socket *so, void *ub, int isstat64); 100 101 #define FDL_WANT 0x01 102 #define FDL_LOCKED 0x02 103 static int fdcache_lock; 104 105 106 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) 107 FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 108 #endif 109 110 #define NFDCACHE 3 111 112 #define FD_NHASH(ix) \ 113 (&fdhashtbl[(ix) & fdhash]) 114 LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl; 115 u_long fdhash; 116 117 static int fdesc_attr(int fd, struct vnode_attr *vap, vfs_context_t a_context); 118 119 lck_mtx_t fdesc_mtx; 120 lck_grp_t *fdesc_lckgrp; 121 122 static void 123 fdesc_lock(void) 124 { 125 lck_mtx_lock(&fdesc_mtx); 126 } 127 128 static void 129 fdesc_unlock(void) 130 { 131 lck_mtx_unlock(&fdesc_mtx); 132 } 133 134 135 /* 136 * Initialise cache headers, create the devfs node 137 */ 138 int 139 devfs_fdesc_init() 140 { 141 int error = 0; 142 devnode_t *rootdir = dev_root->de_dnp; 143 devdirent_t *direntp; 144 145 /* XXX Make sure you have the right path... */ 146 fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash); 147 fdesc_lckgrp = lck_grp_alloc_init("fdesc", NULL); 148 lck_mtx_init(&fdesc_mtx, fdesc_lckgrp, NULL); 149 150 DEVFS_LOCK(); 151 dev_add_entry("fd", rootdir, DEV_DEVFD, NULL, NULL, NULL, &direntp); 152 devfs_fdesc_makelinks(); 153 DEVFS_UNLOCK(); 154 155 return(error); 156 } 157 158 /* 159 * Called during early startup, no need to synchronize 160 */ 161 int 162 devfs_fdesc_makelinks() 163 { 164 int error = 0; 165 devdirent_t *stdin_ent = NULL, *stdout_ent = NULL, *stderr_ent = NULL; 166 devnode_t *root_devnode = dev_root->de_dnp; 167 168 /* We do this ugliness to get around some "const" warnings */ 169 char in[] = "stdin"; 170 char out[] = "stdout"; 171 char err[] = "stderr"; 172 char zero[] = "fd/0"; 173 char one[] = "fd/1"; 174 char two[] = "fd/2"; 175 176 if ((error = devfs_make_symlink(root_devnode, in, 0555, zero, &stdin_ent))) { 177 printf("Couldn't make stdin, err %d.\n", error); 178 goto bad; 179 } 180 181 if ((error = devfs_make_symlink(root_devnode, out, 0555, one, &stdout_ent))) { 182 printf("Couldn't make stdout, err %d.\n", error); 183 goto bad; 184 } 185 186 if ((error = devfs_make_symlink(root_devnode, err, 0555, two, &stderr_ent))) { 187 printf("Couldn't make stderr, err %d.\n", error); 188 goto bad; 189 } 190 191 return 0; 192 193 bad: 194 if (stdin_ent) { 195 dev_free_name(stdin_ent); 196 } 197 if (stdout_ent) { 198 dev_free_name(stdout_ent); 199 } 200 if (stderr_ent) { 201 dev_free_name(stderr_ent); 202 } 203 204 return error; 205 } 206 207 int 208 fdesc_allocvp(fdntype ftype, int ix, struct mount *mp, struct vnode **vpp, enum vtype vtype, int fdno) 209 { 210 struct fdhashhead *fc; 211 struct fdescnode *fd; 212 int error = 0; 213 int vid = 0; 214 struct vnode_fsparam vfsp; 215 216 fdesc_lock(); 217 218 fc = FD_NHASH(ix); 219 loop: 220 for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) { 221 if (fd->fd_ix == ix && vnode_mount(fd->fd_vnode) == mp) { 222 vid = vnode_vid(fd->fd_vnode); 223 fdesc_unlock(); 224 225 if (vnode_getwithvid(fd->fd_vnode, vid)) 226 goto loop; 227 228 *vpp = fd->fd_vnode; 229 (*vpp)->v_type = vtype; 230 231 return (error); 232 } 233 } 234 235 /* Only one thread can add to the hash at a time */ 236 if (fdcache_lock & FDL_LOCKED) { 237 fdcache_lock |= FDL_WANT; 238 msleep((caddr_t) &fdcache_lock, &fdesc_mtx, PINOD, "fdesc_allocvp", NULL); 239 goto loop; 240 } 241 242 fdcache_lock |= FDL_LOCKED; 243 fdesc_unlock(); 244 245 MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 246 247 vfsp.vnfs_mp = mp; 248 vfsp.vnfs_vtype = vtype; 249 vfsp.vnfs_str = "fdesc"; 250 vfsp.vnfs_dvp = NULL; 251 vfsp.vnfs_fsnode = fd; 252 vfsp.vnfs_cnp = NULL; 253 vfsp.vnfs_vops = fdesc_vnodeop_p; 254 vfsp.vnfs_rdev = 0; 255 vfsp.vnfs_filesize = 0; 256 vfsp.vnfs_flags = VNFS_NOCACHE | VNFS_CANTCACHE; 257 vfsp.vnfs_marksystem = 0; 258 vfsp.vnfs_markroot = 0; 259 260 error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &vfsp, vpp); 261 if (error) { 262 FREE(fd, M_TEMP); 263 fdesc_lock(); 264 goto out; 265 } 266 267 (*vpp)->v_tag = VT_FDESC; 268 fd->fd_vnode = *vpp; 269 fd->fd_type = ftype; 270 fd->fd_fd = -1; 271 fd->fd_link = NULL; 272 fd->fd_ix = ix; 273 fd->fd_fd = fdno; 274 275 fdesc_lock(); 276 277 LIST_INSERT_HEAD(fc, fd, fd_hash); 278 out: 279 /* Hold the lock when we get here */ 280 fdcache_lock &= ~FDL_LOCKED; 281 282 if (fdcache_lock & FDL_WANT) { 283 fdcache_lock &= ~FDL_WANT; 284 wakeup((caddr_t) &fdcache_lock); 285 } 286 287 fdesc_unlock(); 288 289 return (error); 290 } 291 292 /* 293 * vp is the current namei directory 294 * ndp is the name to locate in that directory... 295 * 296 * This vnop should only be called on the special directory /dev/fd. 297 */ 298 int 299 devfs_devfd_lookup(struct vnop_lookup_args *ap) 300 { 301 struct vnode **vpp = ap->a_vpp; 302 struct vnode *dvp = ap->a_dvp; 303 struct componentname *cnp = ap->a_cnp; 304 char *pname = cnp->cn_nameptr; 305 struct proc *p = vfs_context_proc(ap->a_context); 306 int numfiles = p->p_fd->fd_nfiles; 307 int fd; 308 int error; 309 struct vnode *fvp; 310 311 if (cnp->cn_namelen == 1 && *pname == '.') { 312 *vpp = dvp; 313 314 if ( (error = vnode_get(dvp)) ) { 315 return(error); 316 } 317 return (0); 318 } 319 320 fd = 0; 321 while (*pname >= '0' && *pname <= '9') { 322 fd = 10 * fd + *pname++ - '0'; 323 if (fd >= numfiles) 324 break; 325 } 326 327 if (*pname != '\0') { 328 error = ENOENT; 329 goto bad; 330 } 331 332 if (fd < 0 || fd >= numfiles || 333 *fdfile(p, fd) == NULL || 334 (*fdflags(p, fd) & UF_RESERVED)) { 335 error = EBADF; 336 goto bad; 337 } 338 339 error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp, VNON, fd); 340 if (error) 341 goto bad; 342 *vpp = fvp; 343 return (0); 344 345 bad: 346 *vpp = NULL; 347 return (error); 348 } 349 350 int 351 fdesc_open(struct vnop_open_args *ap) 352 { 353 struct vnode *vp = ap->a_vp; 354 thread_t thr = vfs_context_thread(ap->a_context); 355 uthread_t uu; 356 int error = 0; 357 358 if (thr == NULL) 359 return (EINVAL); 360 361 uu = get_bsdthread_info(thr); 362 363 switch (VTOFDESC(vp)->fd_type) { 364 case Fdesc: 365 /* 366 * XXX Kludge: set uu->uu_dupfd to contain the value of the 367 * the file descriptor being sought for duplication. The error 368 * return ensures that the vnode for this device will be 369 * released by vn_open. Open will detect this special error and 370 * take the actions in dupfdopen. Other callers of vn_open or 371 * vnop_open will simply report the error. 372 */ 373 uu->uu_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 374 error = ENODEV; 375 break; 376 default: 377 panic("Invalid type for fdesc node!"); 378 break; 379 } 380 381 return (error); 382 } 383 384 static int 385 fdesc_attr(int fd, struct vnode_attr *vap, vfs_context_t a_context) 386 { 387 struct fileproc *fp; 388 struct proc *p = vfs_context_proc(a_context); 389 struct stat stb; 390 int error; 391 392 if ((error = fp_lookup(p, fd, &fp, 0))) 393 return (error); 394 switch (fp->f_fglob->fg_type) { 395 case DTYPE_VNODE: 396 if((error = vnode_getwithref((struct vnode *) fp->f_fglob->fg_data)) != 0) { 397 break; 398 } 399 if ((error = vnode_authorize((struct vnode *)fp->f_fglob->fg_data, 400 NULL, 401 KAUTH_VNODE_READ_ATTRIBUTES | KAUTH_VNODE_READ_SECURITY, 402 a_context)) == 0) 403 error = vnode_getattr((struct vnode *)fp->f_fglob->fg_data, vap, a_context); 404 if (error == 0 && vap->va_type == VDIR) { 405 /* 406 * directories can cause loops in the namespace, 407 * so turn off the 'x' bits to avoid trouble. 408 * 409 * XXX ACLs break this, of course 410 */ 411 vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6)); 412 } 413 (void)vnode_put((struct vnode *) fp->f_fglob->fg_data); 414 break; 415 416 case DTYPE_SOCKET: 417 case DTYPE_PIPE: 418 #if SOCKETS 419 if (fp->f_fglob->fg_type == DTYPE_SOCKET) 420 error = soo_stat((struct socket *)fp->f_fglob->fg_data, (void *)&stb, 0); 421 else 422 #endif /* SOCKETS */ 423 error = pipe_stat((struct pipe *)fp->f_fglob->fg_data, (void *)&stb, 0); 424 425 if (error == 0) { 426 if (fp->f_fglob->fg_type == DTYPE_SOCKET) 427 VATTR_RETURN(vap, va_type, VSOCK); 428 else 429 VATTR_RETURN(vap, va_type, VFIFO); 430 431 VATTR_RETURN(vap, va_mode, stb.st_mode); 432 VATTR_RETURN(vap, va_nlink, stb.st_nlink); 433 VATTR_RETURN(vap, va_uid, stb.st_uid); 434 VATTR_RETURN(vap, va_gid, stb.st_gid); 435 VATTR_RETURN(vap, va_fsid, stb.st_dev); 436 VATTR_RETURN(vap, va_fileid, stb.st_ino); 437 VATTR_RETURN(vap, va_data_size, stb.st_size); 438 VATTR_RETURN(vap, va_access_time, stb.st_atimespec); 439 VATTR_RETURN(vap, va_modify_time, stb.st_mtimespec); 440 VATTR_RETURN(vap, va_change_time, stb.st_ctimespec); 441 VATTR_RETURN(vap, va_gen, stb.st_gen); 442 VATTR_RETURN(vap, va_flags, stb.st_flags); 443 VATTR_RETURN(vap, va_rdev, stb.st_rdev); 444 VATTR_RETURN(vap, va_total_alloc, stb.st_blocks * stb.st_blksize); 445 VATTR_RETURN(vap, va_acl, NULL); 446 } 447 break; 448 449 default: 450 error = EBADF; 451 } 452 453 fp_drop(p, fd, fp, 0); 454 return (error); 455 } 456 457 int 458 fdesc_getattr(struct vnop_getattr_args *ap) 459 { 460 struct vnode *vp = ap->a_vp; 461 struct vnode_attr *vap = ap->a_vap; 462 unsigned fd; 463 int error = 0; 464 465 switch (VTOFDESC(vp)->fd_type) { 466 case Fdesc: 467 fd = VTOFDESC(vp)->fd_fd; 468 error = fdesc_attr(fd, vap, ap->a_context); 469 break; 470 471 default: 472 panic("Invalid type for an fdesc node!\n"); 473 break; 474 } 475 476 /* 477 * Yes, we do this without locking, but this value is always just 478 * a snapshot. 479 */ 480 if (error == 0) { 481 vp->v_type = vap->va_type; 482 483 /* We need an inactive to reset type to VNON */ 484 vnode_setneedinactive(vp); 485 } 486 487 return (error); 488 } 489 490 int 491 fdesc_setattr(struct vnop_setattr_args *ap) 492 { 493 struct fileproc *fp; 494 unsigned fd; 495 int error; 496 struct proc * p = vfs_context_proc(ap->a_context); 497 498 /* 499 * Can't mess with the root vnode 500 */ 501 switch (VTOFDESC(ap->a_vp)->fd_type) { 502 case Fdesc: 503 break; 504 default: 505 panic("Invalid type for an fdesc node!\n"); 506 return (EACCES); 507 } 508 509 fd = VTOFDESC(ap->a_vp)->fd_fd; 510 if ((error = fp_lookup(vfs_context_proc(ap->a_context), fd, &fp, 0))) 511 return (error); 512 513 /* 514 * Can setattr the underlying vnode, but not sockets! 515 */ 516 switch (fp->f_fglob->fg_type) { 517 case DTYPE_VNODE: 518 { 519 if ((error = vnode_getwithref((struct vnode *) fp->f_fglob->fg_data)) != 0) 520 break; 521 error = vnode_setattr((struct vnode *) fp->f_fglob->fg_data, ap->a_vap, ap->a_context); 522 (void)vnode_put((struct vnode *) fp->f_fglob->fg_data); 523 break; 524 } 525 526 case DTYPE_SOCKET: 527 case DTYPE_PIPE: 528 error = 0; 529 break; 530 531 default: 532 kprintf("fp->f_fglob->fg_type = %d\n", fp->f_fglob->fg_type); 533 error = EBADF; 534 break; 535 } 536 537 fp_drop(p, fd, fp, 0); 538 return (error); 539 } 540 541 #define UIO_MX 16 542 543 /* 544 static struct dirtmp { 545 u_int32_t d_fileno; 546 u_short d_reclen; 547 u_short d_namlen; 548 char d_name[8]; 549 } rootent[] = { 550 { FD_DEVFD, UIO_MX, 2, "fd" }, 551 { FD_STDIN, UIO_MX, 5, "stdin" }, 552 { FD_STDOUT, UIO_MX, 6, "stdout" }, 553 { FD_STDERR, UIO_MX, 6, "stderr" }, 554 { 0, 0, 0, "" } 555 }; 556 */ 557 558 /* Only called on /dev/fd */ 559 int 560 devfs_devfd_readdir(struct vnop_readdir_args *ap) 561 { 562 struct uio *uio = ap->a_uio; 563 struct proc *p = current_proc(); 564 int i, error; 565 566 /* 567 * We don't allow exporting fdesc mounts, and currently local 568 * requests do not need cookies. 569 */ 570 if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF)) 571 return (EINVAL); 572 573 i = uio->uio_offset / UIO_MX; 574 error = 0; 575 while (uio_resid(uio) > 0) { 576 if (i >= p->p_fd->fd_nfiles) 577 break; 578 579 if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) { 580 struct dirent d; 581 struct dirent *dp = &d; 582 583 bzero((caddr_t) dp, UIO_MX); 584 585 dp->d_namlen = snprintf(dp->d_name, sizeof(dp->d_name), 586 "%d", i); 587 dp->d_reclen = UIO_MX; 588 dp->d_type = DT_UNKNOWN; 589 dp->d_fileno = i + FD_STDIN; 590 /* 591 * And ship to userland 592 */ 593 error = uiomove((caddr_t) dp, UIO_MX, uio); 594 if (error) 595 break; 596 } 597 i++; 598 } 599 600 uio->uio_offset = i * UIO_MX; 601 return (error); 602 } 603 604 int 605 fdesc_read(__unused struct vnop_read_args *ap) 606 { 607 return (ENOTSUP); 608 } 609 610 int 611 fdesc_write(__unused struct vnop_write_args *ap) 612 { 613 return (ENOTSUP); 614 } 615 616 int 617 fdesc_ioctl(__unused struct vnop_ioctl_args *ap) 618 { 619 return (ENOTSUP); 620 } 621 622 int 623 fdesc_select(__unused struct vnop_select_args *ap) 624 { 625 return (ENOTSUP); 626 } 627 628 int 629 fdesc_inactive(struct vnop_inactive_args *ap) 630 { 631 struct vnode *vp = ap->a_vp; 632 633 /* 634 * Clear out the v_type field to avoid 635 * nasty things happening in vgone(). 636 */ 637 vp->v_type = VNON; 638 639 return (0); 640 } 641 642 int 643 fdesc_reclaim(struct vnop_reclaim_args *ap) 644 { 645 struct vnode *vp = ap->a_vp; 646 struct fdescnode *fd = VTOFDESC(vp); 647 648 fdesc_lock(); 649 650 LIST_REMOVE(fd, fd_hash); 651 FREE(vp->v_data, M_TEMP); 652 vp->v_data = NULL; 653 654 fdesc_unlock(); 655 656 return (0); 657 } 658 659 /* 660 * Return POSIX pathconf information applicable to special devices. 661 */ 662 int 663 fdesc_pathconf(struct vnop_pathconf_args *ap) 664 { 665 666 switch (ap->a_name) { 667 case _PC_LINK_MAX: 668 *ap->a_retval = LINK_MAX; 669 return (0); 670 case _PC_MAX_CANON: 671 *ap->a_retval = MAX_CANON; 672 return (0); 673 case _PC_MAX_INPUT: 674 *ap->a_retval = MAX_INPUT; 675 return (0); 676 case _PC_PIPE_BUF: 677 *ap->a_retval = PIPE_BUF; 678 return (0); 679 case _PC_CHOWN_RESTRICTED: 680 *ap->a_retval = 200112; /* _POSIX_CHOWN_RESTRICTED */ 681 return (0); 682 case _PC_VDISABLE: 683 *ap->a_retval = _POSIX_VDISABLE; 684 return (0); 685 default: 686 return (EINVAL); 687 } 688 /* NOTREACHED */ 689 } 690 691 /* 692 * /dev/fd "should never get here" operation 693 */ 694 int 695 fdesc_badop(void) 696 { 697 698 return (ENOTSUP); 699 /* NOTREACHED */ 700 } 701 702 #define VOPFUNC int (*)(void *) 703 704 #define fdesc_create (int (*) (struct vnop_create_args *))eopnotsupp 705 #define fdesc_mknod (int (*) (struct vnop_mknod_args *))eopnotsupp 706 #define fdesc_close (int (*) (struct vnop_close_args *))nullop 707 #define fdesc_access (int (*) (struct vnop_access_args *))nullop 708 #define fdesc_mmap (int (*) (struct vnop_mmap_args *))eopnotsupp 709 #define fdesc_revoke nop_revoke 710 #define fdesc_fsync (int (*) (struct vnop_fsync_args *))nullop 711 #define fdesc_remove (int (*) (struct vnop_remove_args *))eopnotsupp 712 #define fdesc_link (int (*) (struct vnop_link_args *))eopnotsupp 713 #define fdesc_rename (int (*) (struct vnop_rename_args *))eopnotsupp 714 #define fdesc_mkdir (int (*) (struct vnop_mkdir_args *))eopnotsupp 715 #define fdesc_rmdir (int (*) (struct vnop_rmdir_args *))eopnotsupp 716 #define fdesc_symlink (int (*) (struct vnop_symlink_args *))eopnotsupp 717 #define fdesc_strategy (int (*) (struct vnop_strategy_args *))fdesc_badop 718 #define fdesc_advlock (int (*) (struct vnop_advlock_args *))eopnotsupp 719 #define fdesc_bwrite (int (*) (struct vnop_bwrite_args *))eopnotsupp 720 #define fdesc_blktooff (int (*) (struct vnop_blktooff_args *))eopnotsupp 721 #define fdesc_offtoblk (int (*) (struct vnop_offtoblk_args *))eopnotsupp 722 #define fdesc_blockmap (int (*) (struct vnop_blockmap_args *))eopnotsupp 723 724 int (**fdesc_vnodeop_p)(void *); 725 struct vnodeopv_entry_desc devfs_fdesc_vnodeop_entries[] = { 726 { &vnop_default_desc, (VOPFUNC)vn_default_error }, 727 { &vnop_lookup_desc, (VOPFUNC)vn_default_error}, /* lookup */ 728 { &vnop_create_desc, (VOPFUNC)fdesc_create }, /* create */ 729 { &vnop_mknod_desc, (VOPFUNC)fdesc_mknod }, /* mknod */ 730 { &vnop_open_desc, (VOPFUNC)fdesc_open }, /* open */ 731 { &vnop_close_desc, (VOPFUNC)fdesc_close }, /* close */ 732 { &vnop_access_desc, (VOPFUNC)fdesc_access }, /* access */ 733 { &vnop_getattr_desc, (VOPFUNC)fdesc_getattr }, /* getattr */ 734 { &vnop_setattr_desc, (VOPFUNC)fdesc_setattr }, /* setattr */ 735 { &vnop_read_desc, (VOPFUNC)fdesc_read }, /* read */ 736 { &vnop_write_desc, (VOPFUNC)fdesc_write }, /* write */ 737 { &vnop_ioctl_desc, (VOPFUNC)fdesc_ioctl }, /* ioctl */ 738 { &vnop_select_desc, (VOPFUNC)fdesc_select }, /* select */ 739 { &vnop_revoke_desc, (VOPFUNC)fdesc_revoke }, /* revoke */ 740 { &vnop_mmap_desc, (VOPFUNC)fdesc_mmap }, /* mmap */ 741 { &vnop_fsync_desc, (VOPFUNC)fdesc_fsync }, /* fsync */ 742 { &vnop_remove_desc, (VOPFUNC)fdesc_remove }, /* remove */ 743 { &vnop_link_desc, (VOPFUNC)fdesc_link }, /* link */ 744 { &vnop_rename_desc, (VOPFUNC)fdesc_rename }, /* rename */ 745 { &vnop_mkdir_desc, (VOPFUNC)fdesc_mkdir }, /* mkdir */ 746 { &vnop_rmdir_desc, (VOPFUNC)fdesc_rmdir }, /* rmdir */ 747 { &vnop_symlink_desc, (VOPFUNC)fdesc_symlink }, /* symlink */ 748 { &vnop_readdir_desc, (VOPFUNC)vn_default_error},/* readdir */ 749 { &vnop_readlink_desc, (VOPFUNC)err_readlink}, /* readlink */ 750 { &vnop_inactive_desc, (VOPFUNC)fdesc_inactive },/* inactive */ 751 { &vnop_reclaim_desc, (VOPFUNC)fdesc_reclaim }, /* reclaim */ 752 { &vnop_strategy_desc, (VOPFUNC)fdesc_strategy }, /* strategy */ 753 { &vnop_pathconf_desc, (VOPFUNC)fdesc_pathconf }, /* pathconf */ 754 { &vnop_advlock_desc, (VOPFUNC)fdesc_advlock }, /* advlock */ 755 { &vnop_bwrite_desc, (VOPFUNC)fdesc_bwrite }, /* bwrite */ 756 { &vnop_pagein_desc, (VOPFUNC)err_pagein }, /* pagein */ 757 { &vnop_pageout_desc, (VOPFUNC)err_pageout }, /* pageout */ 758 { &vnop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copyfile */ 759 { &vnop_blktooff_desc, (VOPFUNC)fdesc_blktooff }, /* blktooff */ 760 { &vnop_blktooff_desc, (VOPFUNC)fdesc_offtoblk }, /* offtoblk */ 761 { &vnop_blockmap_desc, (VOPFUNC)fdesc_blockmap }, /* blockmap */ 762 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL } 763 }; 764 765 struct vnodeopv_desc devfs_fdesc_vnodeop_opv_desc = 766 { &fdesc_vnodeop_p, devfs_fdesc_vnodeop_entries }; 767 768