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