The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/ibcs2/ibcs2_misc.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1995 Steven Wallace
    3  * Copyright (c) 1994, 1995 Scott Bartram
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This software was developed by the Computer Systems Engineering group
    8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
    9  * contributed to Berkeley.
   10  *
   11  * All advertising materials mentioning features or use of this software
   12  * must display the following acknowledgement:
   13  *      This product includes software developed by the University of
   14  *      California, Lawrence Berkeley Laboratory.
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  * 3. All advertising materials mentioning features or use of this software
   25  *    must display the following acknowledgement:
   26  *      This product includes software developed by the University of
   27  *      California, Berkeley and its contributors.
   28  * 4. Neither the name of the University nor the names of its contributors
   29  *    may be used to endorse or promote products derived from this software
   30  *    without specific prior written permission.
   31  *
   32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   42  * SUCH DAMAGE.
   43  *
   44  * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 
   45  *
   46  *      @(#)sun_misc.c  8.1 (Berkeley) 6/18/93
   47  */
   48 
   49 #include <sys/cdefs.h>
   50 __FBSDID("$FreeBSD: releng/5.2/sys/i386/ibcs2/ibcs2_misc.c 121016 2003-10-12 04:25:26Z tjr $");
   51 
   52 /*
   53  * IBCS2 compatibility module.
   54  *
   55  * IBCS2 system calls that are implemented differently in BSD are
   56  * handled here.
   57  */
   58 #include "opt_mac.h"
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/dirent.h>
   63 #include <sys/fcntl.h>
   64 #include <sys/filedesc.h>
   65 #include <sys/kernel.h>
   66 #include <sys/lock.h>
   67 #include <sys/mac.h>
   68 #include <sys/malloc.h>
   69 #include <sys/file.h>                   /* Must come after sys/malloc.h */
   70 #include <sys/mutex.h>
   71 #include <sys/reboot.h>
   72 #include <sys/resourcevar.h>
   73 #include <sys/stat.h>
   74 #include <sys/sysctl.h>
   75 #include <sys/sysproto.h>
   76 #include <sys/time.h>
   77 #include <sys/times.h>
   78 #include <sys/vnode.h>
   79 #include <sys/wait.h>
   80 
   81 #include <machine/cpu.h>
   82 
   83 #include <i386/ibcs2/ibcs2_dirent.h>
   84 #include <i386/ibcs2/ibcs2_signal.h>
   85 #include <i386/ibcs2/ibcs2_proto.h>
   86 #include <i386/ibcs2/ibcs2_unistd.h>
   87 #include <i386/ibcs2/ibcs2_util.h>
   88 #include <i386/ibcs2/ibcs2_utime.h>
   89 #include <i386/ibcs2/ibcs2_xenix.h>
   90 
   91 int
   92 ibcs2_ulimit(td, uap)
   93         struct thread *td;
   94         struct ibcs2_ulimit_args *uap;
   95 {
   96 #ifdef notyet
   97         int error;
   98         struct rlimit rl;
   99         struct setrlimit_args {
  100                 int resource;
  101                 struct rlimit *rlp;
  102         } sra;
  103 #endif
  104 #define IBCS2_GETFSIZE          1
  105 #define IBCS2_SETFSIZE          2
  106 #define IBCS2_GETPSIZE          3
  107 #define IBCS2_GETDTABLESIZE     4
  108         
  109         switch (uap->cmd) {
  110         case IBCS2_GETFSIZE:
  111                 td->td_retval[0] = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur;
  112                 if (td->td_retval[0] == -1) td->td_retval[0] = 0x7fffffff;
  113                 return 0;
  114         case IBCS2_SETFSIZE:    /* XXX - fix this */
  115 #ifdef notyet
  116                 rl.rlim_cur = uap->newlimit;
  117                 sra.resource = RLIMIT_FSIZE;
  118                 sra.rlp = &rl;
  119                 error = setrlimit(td, &sra);
  120                 if (!error)
  121                         td->td_retval[0] = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur;
  122                 else
  123                         DPRINTF(("failed "));
  124                 return error;
  125 #else
  126                 td->td_retval[0] = uap->newlimit;
  127                 return 0;
  128 #endif
  129         case IBCS2_GETPSIZE:
  130                 mtx_assert(&Giant, MA_OWNED);
  131                 td->td_retval[0] = td->td_proc->p_rlimit[RLIMIT_RSS].rlim_cur; /* XXX */
  132                 return 0;
  133         case IBCS2_GETDTABLESIZE:
  134                 uap->cmd = IBCS2_SC_OPEN_MAX;
  135                 return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap);
  136         default:
  137                 return ENOSYS;
  138         }
  139 }
  140 
  141 #define IBCS2_WSTOPPED       0177
  142 #define IBCS2_STOPCODE(sig)  ((sig) << 8 | IBCS2_WSTOPPED)
  143 int
  144 ibcs2_wait(td, uap)
  145         struct thread *td;
  146         struct ibcs2_wait_args *uap;
  147 {
  148         int error, status;
  149         struct wait_args w4;
  150         struct trapframe *tf = td->td_frame;
  151         
  152         w4.rusage = NULL;
  153         if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
  154             == (PSL_Z|PSL_PF|PSL_N|PSL_V)) {
  155                 /* waitpid */
  156                 w4.pid = uap->a1;
  157                 w4.status = (int *)uap->a2;
  158                 w4.options = uap->a3;
  159         } else {
  160                 /* wait */
  161                 w4.pid = WAIT_ANY;
  162                 w4.status = (int *)uap->a1;
  163                 w4.options = 0;
  164         }
  165         if ((error = wait4(td, &w4)) != 0)
  166                 return error;
  167         if (w4.status)  {       /* this is real iBCS brain-damage */
  168                 error = copyin((caddr_t)w4.status, (caddr_t)&status,
  169                                sizeof(w4.status));
  170                 if(error)
  171                   return error;
  172 
  173                 /*
  174                  * Convert status/signal result. We must validate the
  175                  * signal number stored in the exit status in case
  176                  * the user changed it between wait4()'s copyout()
  177                  * and our copyin().
  178                  */
  179                 if (WIFSTOPPED(status)) {
  180                         if (WSTOPSIG(status) <= 0 ||
  181                             WSTOPSIG(status) > IBCS2_SIGTBLSZ)
  182                                 return (EINVAL);
  183                         status =
  184                           IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]);
  185                 } else if (WIFSIGNALED(status)) {
  186                         if (WTERMSIG(status) <= 0 ||
  187                             WTERMSIG(status) > IBCS2_SIGTBLSZ)
  188                                 return (EINVAL);
  189                         status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))];
  190                 }
  191                 /* else exit status -- identical */
  192 
  193                 /* record result/status */
  194                 td->td_retval[1] = status;
  195                 return copyout((caddr_t)&status, (caddr_t)w4.status,
  196                                sizeof(w4.status));
  197         }
  198 
  199         return 0;
  200 }
  201 
  202 int
  203 ibcs2_execv(td, uap)
  204         struct thread *td;
  205         struct ibcs2_execv_args *uap;
  206 {
  207         struct execve_args ea;
  208         caddr_t sg = stackgap_init();
  209 
  210         CHECKALTEXIST(td, &sg, uap->path);
  211         ea.fname = uap->path;
  212         ea.argv = uap->argp;
  213         ea.envv = NULL;
  214         return execve(td, &ea);
  215 }
  216 
  217 int
  218 ibcs2_execve(td, uap) 
  219         struct thread *td;
  220         struct ibcs2_execve_args *uap;
  221 {
  222         caddr_t sg = stackgap_init();
  223         CHECKALTEXIST(td, &sg, uap->path);
  224         return execve(td, (struct execve_args *)uap);
  225 }
  226 
  227 int
  228 ibcs2_umount(td, uap)
  229         struct thread *td;
  230         struct ibcs2_umount_args *uap;
  231 {
  232         struct unmount_args um;
  233 
  234         um.path = uap->name;
  235         um.flags = 0;
  236         return unmount(td, &um);
  237 }
  238 
  239 int
  240 ibcs2_mount(td, uap)
  241         struct thread *td;
  242         struct ibcs2_mount_args *uap;
  243 {
  244 #ifdef notyet
  245         int oflags = uap->flags, nflags, error;
  246         char fsname[MFSNAMELEN];
  247 
  248         if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5))
  249                 return (EINVAL);
  250         if ((oflags & IBCS2_MS_NEWTYPE) == 0)
  251                 return (EINVAL);
  252         nflags = 0;
  253         if (oflags & IBCS2_MS_RDONLY)
  254                 nflags |= MNT_RDONLY;
  255         if (oflags & IBCS2_MS_NOSUID)
  256                 nflags |= MNT_NOSUID;
  257         if (oflags & IBCS2_MS_REMOUNT)
  258                 nflags |= MNT_UPDATE;
  259         uap->flags = nflags;
  260 
  261         if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname,
  262                               (u_int *)0))
  263                 return (error);
  264 
  265         if (strcmp(fsname, "4.2") == 0) {
  266                 uap->type = (caddr_t)STACK_ALLOC();
  267                 if (error = copyout("ufs", uap->type, sizeof("ufs")))
  268                         return (error);
  269         } else if (strcmp(fsname, "nfs") == 0) {
  270                 struct ibcs2_nfs_args sna;
  271                 struct sockaddr_in sain;
  272                 struct nfs_args na;
  273                 struct sockaddr sa;
  274 
  275                 if (error = copyin(uap->data, &sna, sizeof sna))
  276                         return (error);
  277                 if (error = copyin(sna.addr, &sain, sizeof sain))
  278                         return (error);
  279                 bcopy(&sain, &sa, sizeof sa);
  280                 sa.sa_len = sizeof(sain);
  281                 uap->data = (caddr_t)STACK_ALLOC();
  282                 na.addr = (struct sockaddr *)((int)uap->data + sizeof na);
  283                 na.sotype = SOCK_DGRAM;
  284                 na.proto = IPPROTO_UDP;
  285                 na.fh = (nfsv2fh_t *)sna.fh;
  286                 na.flags = sna.flags;
  287                 na.wsize = sna.wsize;
  288                 na.rsize = sna.rsize;
  289                 na.timeo = sna.timeo;
  290                 na.retrans = sna.retrans;
  291                 na.hostname = sna.hostname;
  292 
  293                 if (error = copyout(&sa, na.addr, sizeof sa))
  294                         return (error);
  295                 if (error = copyout(&na, uap->data, sizeof na))
  296                         return (error);
  297         }
  298         return (mount(td, uap));
  299 #else
  300         return EINVAL;
  301 #endif
  302 }
  303 
  304 /*
  305  * Read iBCS2-style directory entries.  We suck them into kernel space so
  306  * that they can be massaged before being copied out to user code.  Like
  307  * SunOS, we squish out `empty' entries.
  308  *
  309  * This is quite ugly, but what do you expect from compatibility code?
  310  */
  311 
  312 int
  313 ibcs2_getdents(td, uap)
  314         struct thread *td;
  315         register struct ibcs2_getdents_args *uap;
  316 {
  317         register struct vnode *vp;
  318         register caddr_t inp, buf;      /* BSD-format */
  319         register int len, reclen;       /* BSD-format */
  320         register caddr_t outp;          /* iBCS2-format */
  321         register int resid;             /* iBCS2-format */
  322         struct file *fp;
  323         struct uio auio;
  324         struct iovec aiov;
  325         struct ibcs2_dirent idb;
  326         off_t off;                      /* true file offset */
  327         int buflen, error, eofflag;
  328         u_long *cookies = NULL, *cookiep;
  329         int ncookies;
  330 #define BSD_DIRENT(cp)          ((struct dirent *)(cp))
  331 #define IBCS2_RECLEN(reclen)    (reclen + sizeof(u_short))
  332 
  333         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
  334                 return (error);
  335         if ((fp->f_flag & FREAD) == 0) {
  336                 fdrop(fp, td);
  337                 return (EBADF);
  338         }
  339         vp = fp->f_vnode;
  340         if (vp->v_type != VDIR) {       /* XXX  vnode readdir op should do this */
  341                 fdrop(fp, td);
  342                 return (EINVAL);
  343         }
  344 
  345         off = fp->f_offset;
  346 #define DIRBLKSIZ       512             /* XXX we used to use ufs's DIRBLKSIZ */
  347         buflen = max(DIRBLKSIZ, uap->nbytes);
  348         buflen = min(buflen, MAXBSIZE);
  349         buf = malloc(buflen, M_TEMP, M_WAITOK);
  350         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  351 again:
  352         aiov.iov_base = buf;
  353         aiov.iov_len = buflen;
  354         auio.uio_iov = &aiov;
  355         auio.uio_iovcnt = 1;
  356         auio.uio_rw = UIO_READ;
  357         auio.uio_segflg = UIO_SYSSPACE;
  358         auio.uio_td = td;
  359         auio.uio_resid = buflen;
  360         auio.uio_offset = off;
  361 
  362         if (cookies) {
  363                 free(cookies, M_TEMP);
  364                 cookies = NULL;
  365         }
  366 
  367 #ifdef MAC
  368         error = mac_check_vnode_readdir(td->td_ucred, vp);
  369         if (error)
  370                 goto out;
  371 #endif
  372 
  373         /*
  374          * First we read into the malloc'ed buffer, then
  375          * we massage it into user space, one record at a time.
  376          */
  377         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0)
  378                 goto out;
  379         inp = buf;
  380         outp = uap->buf;
  381         resid = uap->nbytes;
  382         if ((len = buflen - auio.uio_resid) <= 0)
  383                 goto eof;
  384 
  385         cookiep = cookies;
  386 
  387         if (cookies) {
  388                 /*
  389                  * When using cookies, the vfs has the option of reading from
  390                  * a different offset than that supplied (UFS truncates the
  391                  * offset to a block boundary to make sure that it never reads
  392                  * partway through a directory entry, even if the directory
  393                  * has been compacted).
  394                  */
  395                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
  396                         len -= BSD_DIRENT(inp)->d_reclen;
  397                         inp += BSD_DIRENT(inp)->d_reclen;
  398                         cookiep++;
  399                         ncookies--;
  400                 }
  401         }
  402 
  403         for (; len > 0; len -= reclen) {
  404                 if (cookiep && ncookies == 0)
  405                         break;
  406                 reclen = BSD_DIRENT(inp)->d_reclen;
  407                 if (reclen & 3) {
  408                         printf("ibcs2_getdents: reclen=%d\n", reclen);
  409                         error = EFAULT;
  410                         goto out;
  411                 }
  412                 if (BSD_DIRENT(inp)->d_fileno == 0) {
  413                         inp += reclen;  /* it is a hole; squish it out */
  414                         if (cookiep) {
  415                                 off = *cookiep++;
  416                                 ncookies--;
  417                         } else
  418                                 off += reclen;
  419                         continue;
  420                 }
  421                 if (reclen > len || resid < IBCS2_RECLEN(reclen)) {
  422                         /* entry too big for buffer, so just stop */
  423                         outp++;
  424                         break;
  425                 }
  426                 /*
  427                  * Massage in place to make an iBCS2-shaped dirent (otherwise
  428                  * we have to worry about touching user memory outside of
  429                  * the copyout() call).
  430                  */
  431                 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno;
  432                 idb.d_off = (ibcs2_off_t)off;
  433                 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen);
  434                 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 ||
  435                     (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10,
  436                                      BSD_DIRENT(inp)->d_namlen + 1)) != 0)
  437                         goto out;
  438                 /* advance past this real entry */
  439                 if (cookiep) {
  440                         off = *cookiep++;
  441                         ncookies--;
  442                 } else
  443                         off += reclen;
  444                 inp += reclen;
  445                 /* advance output past iBCS2-shaped entry */
  446                 outp += IBCS2_RECLEN(reclen);
  447                 resid -= IBCS2_RECLEN(reclen);
  448         }
  449         /* if we squished out the whole block, try again */
  450         if (outp == uap->buf)
  451                 goto again;
  452         fp->f_offset = off;             /* update the vnode offset */
  453 eof:
  454         td->td_retval[0] = uap->nbytes - resid;
  455 out:
  456         VOP_UNLOCK(vp, 0, td);
  457         fdrop(fp, td);
  458         if (cookies)
  459                 free(cookies, M_TEMP);
  460         free(buf, M_TEMP);
  461         return (error);
  462 }
  463 
  464 int
  465 ibcs2_read(td, uap)
  466         struct thread *td;
  467         struct ibcs2_read_args *uap;
  468 {
  469         register struct vnode *vp;
  470         register caddr_t inp, buf;      /* BSD-format */
  471         register int len, reclen;       /* BSD-format */
  472         register caddr_t outp;          /* iBCS2-format */
  473         register int resid;             /* iBCS2-format */
  474         struct file *fp;
  475         struct uio auio;
  476         struct iovec aiov;
  477         struct ibcs2_direct {
  478                 ibcs2_ino_t ino;
  479                 char name[14];
  480         } idb;
  481         off_t off;                      /* true file offset */
  482         int buflen, error, eofflag, size;
  483         u_long *cookies = NULL, *cookiep;
  484         int ncookies;
  485 
  486         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
  487                 if (error == EINVAL)
  488                         return read(td, (struct read_args *)uap);
  489                 else
  490                         return error;
  491         }
  492         if ((fp->f_flag & FREAD) == 0) {
  493                 fdrop(fp, td);
  494                 return (EBADF);
  495         }
  496         vp = fp->f_vnode;
  497         if (vp->v_type != VDIR) {
  498                 fdrop(fp, td);
  499                 return read(td, (struct read_args *)uap);
  500         }
  501 
  502         off = fp->f_offset;
  503         if (vp->v_type != VDIR)
  504                 return read(td, (struct read_args *)uap);
  505 
  506         DPRINTF(("ibcs2_read: read directory\n"));
  507 
  508         buflen = max(DIRBLKSIZ, uap->nbytes);
  509         buflen = min(buflen, MAXBSIZE);
  510         buf = malloc(buflen, M_TEMP, M_WAITOK);
  511         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  512 again:
  513         aiov.iov_base = buf;
  514         aiov.iov_len = buflen;
  515         auio.uio_iov = &aiov;
  516         auio.uio_iovcnt = 1;
  517         auio.uio_rw = UIO_READ;
  518         auio.uio_segflg = UIO_SYSSPACE;
  519         auio.uio_td = td;
  520         auio.uio_resid = buflen;
  521         auio.uio_offset = off;
  522 
  523         if (cookies) {
  524                 free(cookies, M_TEMP);
  525                 cookies = NULL;
  526         }
  527 
  528 #ifdef MAC
  529         error = mac_check_vnode_readdir(td->td_ucred, vp);
  530         if (error)
  531                 goto out;
  532 #endif
  533 
  534         /*
  535          * First we read into the malloc'ed buffer, then
  536          * we massage it into user space, one record at a time.
  537          */
  538         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) {
  539                 DPRINTF(("VOP_READDIR failed: %d\n", error));
  540                 goto out;
  541         }
  542         inp = buf;
  543         outp = uap->buf;
  544         resid = uap->nbytes;
  545         if ((len = buflen - auio.uio_resid) <= 0)
  546                 goto eof;
  547 
  548         cookiep = cookies;
  549 
  550         if (cookies) {
  551                 /*
  552                  * When using cookies, the vfs has the option of reading from
  553                  * a different offset than that supplied (UFS truncates the
  554                  * offset to a block boundary to make sure that it never reads
  555                  * partway through a directory entry, even if the directory
  556                  * has been compacted).
  557                  */
  558                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
  559                         len -= BSD_DIRENT(inp)->d_reclen;
  560                         inp += BSD_DIRENT(inp)->d_reclen;
  561                         cookiep++;
  562                         ncookies--;
  563                 }
  564         }
  565 
  566         for (; len > 0 && resid > 0; len -= reclen) {
  567                 if (cookiep && ncookies == 0)
  568                         break;
  569                 reclen = BSD_DIRENT(inp)->d_reclen;
  570                 if (reclen & 3) {
  571                         printf("ibcs2_read: reclen=%d\n", reclen);
  572                         error = EFAULT;
  573                         goto out;
  574                 }
  575                 if (BSD_DIRENT(inp)->d_fileno == 0) {
  576                         inp += reclen;  /* it is a hole; squish it out */
  577                         if (cookiep) {
  578                                 off = *cookiep++;
  579                                 ncookies--;
  580                         } else
  581                                 off += reclen;
  582                         continue;
  583                 }
  584                 if (reclen > len || resid < sizeof(struct ibcs2_direct)) {
  585                         /* entry too big for buffer, so just stop */
  586                         outp++;
  587                         break;
  588                 }
  589                 /*
  590                  * Massage in place to make an iBCS2-shaped dirent (otherwise
  591                  * we have to worry about touching user memory outside of
  592                  * the copyout() call).
  593                  *
  594                  * TODO: if length(filename) > 14, then break filename into
  595                  * multiple entries and set inode = 0xffff except last
  596                  */
  597                 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe :
  598                         BSD_DIRENT(inp)->d_fileno;
  599                 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size);
  600                 bzero(idb.name + size, 14 - size);
  601                 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0)
  602                         goto out;
  603                 /* advance past this real entry */
  604                 if (cookiep) {
  605                         off = *cookiep++;
  606                         ncookies--;
  607                 } else
  608                         off += reclen;
  609                 inp += reclen;
  610                 /* advance output past iBCS2-shaped entry */
  611                 outp += sizeof(struct ibcs2_direct);
  612                 resid -= sizeof(struct ibcs2_direct);
  613         }
  614         /* if we squished out the whole block, try again */
  615         if (outp == uap->buf)
  616                 goto again;
  617         fp->f_offset = off;             /* update the vnode offset */
  618 eof:
  619         td->td_retval[0] = uap->nbytes - resid;
  620 out:
  621         VOP_UNLOCK(vp, 0, td);
  622         fdrop(fp, td);
  623         if (cookies)
  624                 free(cookies, M_TEMP);
  625         free(buf, M_TEMP);
  626         return (error);
  627 }
  628 
  629 int
  630 ibcs2_mknod(td, uap)
  631         struct thread *td;
  632         struct ibcs2_mknod_args *uap;
  633 {
  634         caddr_t sg = stackgap_init();
  635 
  636         CHECKALTCREAT(td, &sg, uap->path);
  637         if (S_ISFIFO(uap->mode)) {
  638                 struct mkfifo_args ap;
  639                 ap.path = uap->path;
  640                 ap.mode = uap->mode;
  641                 return mkfifo(td, &ap);
  642         } else {
  643                 struct mknod_args ap;
  644                 ap.path = uap->path;
  645                 ap.mode = uap->mode;
  646                 ap.dev = uap->dev;
  647                 return mknod(td, &ap);
  648         }
  649 }
  650 
  651 int
  652 ibcs2_getgroups(td, uap)
  653         struct thread *td;
  654         struct ibcs2_getgroups_args *uap;
  655 {
  656         int error, i;
  657         ibcs2_gid_t *iset = NULL;
  658         struct getgroups_args sa;
  659         gid_t *gp;
  660         caddr_t sg = stackgap_init();
  661 
  662         if (uap->gidsetsize < 0)
  663                 return (EINVAL);
  664         if (uap->gidsetsize > NGROUPS_MAX)
  665                 uap->gidsetsize = NGROUPS_MAX;
  666         sa.gidsetsize = uap->gidsetsize;
  667         if (uap->gidsetsize) {
  668                 sa.gidset = stackgap_alloc(&sg, NGROUPS_MAX *
  669                                                     sizeof(gid_t *));
  670                 iset = stackgap_alloc(&sg, uap->gidsetsize *
  671                                       sizeof(ibcs2_gid_t));
  672         }
  673         if ((error = getgroups(td, &sa)) != 0)
  674                 return error;
  675         if (uap->gidsetsize == 0)
  676                 return 0;
  677 
  678         for (i = 0, gp = sa.gidset; i < td->td_retval[0]; i++)
  679                 iset[i] = (ibcs2_gid_t)*gp++;
  680         if (td->td_retval[0] && (error = copyout((caddr_t)iset,
  681                                           (caddr_t)uap->gidset,
  682                                           sizeof(ibcs2_gid_t) * td->td_retval[0])))
  683                 return error;
  684         return 0;
  685 }
  686 
  687 int
  688 ibcs2_setgroups(td, uap)
  689         struct thread *td;
  690         struct ibcs2_setgroups_args *uap;
  691 {
  692         int error, i;
  693         ibcs2_gid_t *iset;
  694         struct setgroups_args sa;
  695         gid_t *gp;
  696         caddr_t sg = stackgap_init();
  697 
  698         if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX)
  699                 return (EINVAL);
  700         sa.gidsetsize = uap->gidsetsize;
  701         sa.gidset = stackgap_alloc(&sg, sa.gidsetsize *
  702                                             sizeof(gid_t *));
  703         iset = stackgap_alloc(&sg, sa.gidsetsize *
  704                               sizeof(ibcs2_gid_t *));
  705         if (sa.gidsetsize) {
  706                 if ((error = copyin((caddr_t)uap->gidset, (caddr_t)iset, 
  707                                    sizeof(ibcs2_gid_t *) *
  708                                    uap->gidsetsize)) != 0)
  709                         return error;
  710         }
  711         for (i = 0, gp = sa.gidset; i < sa.gidsetsize; i++)
  712                 *gp++ = (gid_t)iset[i];
  713         return setgroups(td, &sa);
  714 }
  715 
  716 int
  717 ibcs2_setuid(td, uap)
  718         struct thread *td;
  719         struct ibcs2_setuid_args *uap;
  720 {
  721         struct setuid_args sa;
  722 
  723         sa.uid = (uid_t)uap->uid;
  724         return setuid(td, &sa);
  725 }
  726 
  727 int
  728 ibcs2_setgid(td, uap)
  729         struct thread *td;
  730         struct ibcs2_setgid_args *uap;
  731 {
  732         struct setgid_args sa;
  733 
  734         sa.gid = (gid_t)uap->gid;
  735         return setgid(td, &sa);
  736 }
  737 
  738 int
  739 ibcs2_time(td, uap)
  740         struct thread *td;
  741         struct ibcs2_time_args *uap;
  742 {
  743         struct timeval tv;
  744 
  745         microtime(&tv);
  746         td->td_retval[0] = tv.tv_sec;
  747         if (uap->tp)
  748                 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp,
  749                                sizeof(ibcs2_time_t));
  750         else
  751                 return 0;
  752 }
  753 
  754 int
  755 ibcs2_pathconf(td, uap)
  756         struct thread *td;
  757         struct ibcs2_pathconf_args *uap;
  758 {
  759         uap->name++;    /* iBCS2 _PC_* defines are offset by one */
  760         return pathconf(td, (struct pathconf_args *)uap);
  761 }
  762 
  763 int
  764 ibcs2_fpathconf(td, uap)
  765         struct thread *td;
  766         struct ibcs2_fpathconf_args *uap;
  767 {
  768         uap->name++;    /* iBCS2 _PC_* defines are offset by one */
  769         return fpathconf(td, (struct fpathconf_args *)uap);
  770 }
  771 
  772 int
  773 ibcs2_sysconf(td, uap)
  774         struct thread *td;
  775         struct ibcs2_sysconf_args *uap;
  776 {
  777         int mib[2], value, len, error;
  778         struct sysctl_args sa;
  779         struct __getrlimit_args ga;
  780 
  781         switch(uap->name) {
  782         case IBCS2_SC_ARG_MAX:
  783                 mib[1] = KERN_ARGMAX;
  784                 break;
  785 
  786         case IBCS2_SC_CHILD_MAX:
  787             {
  788                 caddr_t sg = stackgap_init();
  789 
  790                 ga.which = RLIMIT_NPROC;
  791                 ga.rlp = stackgap_alloc(&sg, sizeof(struct rlimit *));
  792                 if ((error = getrlimit(td, &ga)) != 0)
  793                         return error;
  794                 td->td_retval[0] = ga.rlp->rlim_cur;
  795                 return 0;
  796             }
  797 
  798         case IBCS2_SC_CLK_TCK:
  799                 td->td_retval[0] = hz;
  800                 return 0;
  801 
  802         case IBCS2_SC_NGROUPS_MAX:
  803                 mib[1] = KERN_NGROUPS;
  804                 break;
  805 
  806         case IBCS2_SC_OPEN_MAX:
  807             {
  808                 caddr_t sg = stackgap_init();
  809 
  810                 ga.which = RLIMIT_NOFILE;
  811                 ga.rlp = stackgap_alloc(&sg, sizeof(struct rlimit *));
  812                 if ((error = getrlimit(td, &ga)) != 0)
  813                         return error;
  814                 td->td_retval[0] = ga.rlp->rlim_cur;
  815                 return 0;
  816             }
  817                 
  818         case IBCS2_SC_JOB_CONTROL:
  819                 mib[1] = KERN_JOB_CONTROL;
  820                 break;
  821                 
  822         case IBCS2_SC_SAVED_IDS:
  823                 mib[1] = KERN_SAVED_IDS;
  824                 break;
  825                 
  826         case IBCS2_SC_VERSION:
  827                 mib[1] = KERN_POSIX1;
  828                 break;
  829                 
  830         case IBCS2_SC_PASS_MAX:
  831                 td->td_retval[0] = 128;         /* XXX - should we create PASS_MAX ? */
  832                 return 0;
  833 
  834         case IBCS2_SC_XOPEN_VERSION:
  835                 td->td_retval[0] = 2;           /* XXX: What should that be? */
  836                 return 0;
  837                 
  838         default:
  839                 return EINVAL;
  840         }
  841 
  842         mib[0] = CTL_KERN;
  843         len = sizeof(value);
  844         sa.name = mib;
  845         sa.namelen = 2;
  846         sa.old = &value;
  847         sa.oldlenp = &len;
  848         sa.new = NULL;
  849         sa.newlen = 0;
  850         if ((error = __sysctl(td, &sa)) != 0)
  851                 return error;
  852         td->td_retval[0] = value;
  853         return 0;
  854 }
  855 
  856 int
  857 ibcs2_alarm(td, uap)
  858         struct thread *td;
  859         struct ibcs2_alarm_args *uap;
  860 {
  861         int error;
  862         struct itimerval *itp, *oitp;
  863         struct setitimer_args sa;
  864         caddr_t sg = stackgap_init();
  865 
  866         itp = stackgap_alloc(&sg, sizeof(*itp));
  867         oitp = stackgap_alloc(&sg, sizeof(*oitp));
  868         timevalclear(&itp->it_interval);
  869         itp->it_value.tv_sec = uap->sec;
  870         itp->it_value.tv_usec = 0;
  871 
  872         sa.which = ITIMER_REAL;
  873         sa.itv = itp;
  874         sa.oitv = oitp;
  875         error = setitimer(td, &sa);
  876         if (error)
  877                 return error;
  878         if (oitp->it_value.tv_usec)
  879                 oitp->it_value.tv_sec++;
  880         td->td_retval[0] = oitp->it_value.tv_sec;
  881         return 0;
  882 }
  883 
  884 int
  885 ibcs2_times(td, uap)
  886         struct thread *td;
  887         struct ibcs2_times_args *uap;
  888 {
  889         int error;
  890         struct getrusage_args ga;
  891         struct tms tms;
  892         struct timeval t;
  893         caddr_t sg = stackgap_init();
  894         struct rusage *ru = stackgap_alloc(&sg, sizeof(*ru));
  895 #define CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
  896 
  897         ga.who = RUSAGE_SELF;
  898         ga.rusage = ru;
  899         error = getrusage(td, &ga);
  900         if (error)
  901                 return error;
  902         tms.tms_utime = CONVTCK(ru->ru_utime);
  903         tms.tms_stime = CONVTCK(ru->ru_stime);
  904 
  905         ga.who = RUSAGE_CHILDREN;
  906         error = getrusage(td, &ga);
  907         if (error)
  908                 return error;
  909         tms.tms_cutime = CONVTCK(ru->ru_utime);
  910         tms.tms_cstime = CONVTCK(ru->ru_stime);
  911 
  912         microtime(&t);
  913         td->td_retval[0] = CONVTCK(t);
  914         
  915         return copyout((caddr_t)&tms, (caddr_t)uap->tp,
  916                        sizeof(struct tms));
  917 }
  918 
  919 int
  920 ibcs2_stime(td, uap)
  921         struct thread *td;
  922         struct ibcs2_stime_args *uap;
  923 {
  924         int error;
  925         struct settimeofday_args sa;
  926         caddr_t sg = stackgap_init();
  927 
  928         sa.tv = stackgap_alloc(&sg, sizeof(*sa.tv));
  929         sa.tzp = NULL;
  930         if ((error = copyin((caddr_t)uap->timep,
  931                            &(sa.tv->tv_sec), sizeof(long))) != 0)
  932                 return error;
  933         sa.tv->tv_usec = 0;
  934         if ((error = settimeofday(td, &sa)) != 0)
  935                 return EPERM;
  936         return 0;
  937 }
  938 
  939 int
  940 ibcs2_utime(td, uap)
  941         struct thread *td;
  942         struct ibcs2_utime_args *uap;
  943 {
  944         int error;
  945         struct utimes_args sa;
  946         struct timeval *tp;
  947         caddr_t sg = stackgap_init();
  948 
  949         CHECKALTEXIST(td, &sg, uap->path);
  950         sa.path = uap->path;
  951         if (uap->buf) {
  952                 struct ibcs2_utimbuf ubuf;
  953 
  954                 if ((error = copyin((caddr_t)uap->buf, (caddr_t)&ubuf,
  955                                    sizeof(ubuf))) != 0)
  956                         return error;
  957                 sa.tptr = stackgap_alloc(&sg,
  958                                                   2 * sizeof(struct timeval *));
  959                 tp = (struct timeval *)sa.tptr;
  960                 tp->tv_sec = ubuf.actime;
  961                 tp->tv_usec = 0;
  962                 tp++;
  963                 tp->tv_sec = ubuf.modtime;
  964                 tp->tv_usec = 0;
  965         } else
  966                 sa.tptr = NULL;
  967         return utimes(td, &sa);
  968 }
  969 
  970 int
  971 ibcs2_nice(td, uap)
  972         struct thread *td;
  973         struct ibcs2_nice_args *uap;
  974 {
  975         int error;
  976         struct setpriority_args sa;
  977 
  978         sa.which = PRIO_PROCESS;
  979         sa.who = 0;
  980         sa.prio = td->td_ksegrp->kg_nice + uap->incr;
  981         if ((error = setpriority(td, &sa)) != 0)
  982                 return EPERM;
  983         td->td_retval[0] = td->td_ksegrp->kg_nice;
  984         return 0;
  985 }
  986 
  987 /*
  988  * iBCS2 getpgrp, setpgrp, setsid, and setpgid
  989  */
  990 
  991 int
  992 ibcs2_pgrpsys(td, uap)
  993         struct thread *td;
  994         struct ibcs2_pgrpsys_args *uap;
  995 {
  996         struct proc *p = td->td_proc;
  997         switch (uap->type) {
  998         case 0:                 /* getpgrp */
  999                 PROC_LOCK(p);
 1000                 td->td_retval[0] = p->p_pgrp->pg_id;
 1001                 PROC_UNLOCK(p);
 1002                 return 0;
 1003 
 1004         case 1:                 /* setpgrp */
 1005             {
 1006                 struct setpgid_args sa;
 1007 
 1008                 sa.pid = 0;
 1009                 sa.pgid = 0;
 1010                 setpgid(td, &sa);
 1011                 PROC_LOCK(p);
 1012                 td->td_retval[0] = p->p_pgrp->pg_id;
 1013                 PROC_UNLOCK(p);
 1014                 return 0;
 1015             }
 1016 
 1017         case 2:                 /* setpgid */
 1018             {
 1019                 struct setpgid_args sa;
 1020 
 1021                 sa.pid = uap->pid;
 1022                 sa.pgid = uap->pgid;
 1023                 return setpgid(td, &sa);
 1024             }
 1025 
 1026         case 3:                 /* setsid */
 1027                 return setsid(td, NULL);
 1028 
 1029         default:
 1030                 return EINVAL;
 1031         }
 1032 }
 1033 
 1034 /*
 1035  * XXX - need to check for nested calls
 1036  */
 1037 
 1038 int
 1039 ibcs2_plock(td, uap)
 1040         struct thread *td;
 1041         struct ibcs2_plock_args *uap;
 1042 {
 1043         int error;
 1044 #define IBCS2_UNLOCK    0
 1045 #define IBCS2_PROCLOCK  1
 1046 #define IBCS2_TEXTLOCK  2
 1047 #define IBCS2_DATALOCK  4
 1048 
 1049         
 1050         if ((error = suser(td)) != 0)
 1051                 return EPERM;
 1052         switch(uap->cmd) {
 1053         case IBCS2_UNLOCK:
 1054         case IBCS2_PROCLOCK:
 1055         case IBCS2_TEXTLOCK:
 1056         case IBCS2_DATALOCK:
 1057                 return 0;       /* XXX - TODO */
 1058         }
 1059         return EINVAL;
 1060 }
 1061 
 1062 int
 1063 ibcs2_uadmin(td, uap)
 1064         struct thread *td;
 1065         struct ibcs2_uadmin_args *uap;
 1066 {
 1067 #define SCO_A_REBOOT        1
 1068 #define SCO_A_SHUTDOWN      2
 1069 #define SCO_A_REMOUNT       4
 1070 #define SCO_A_CLOCK         8
 1071 #define SCO_A_SETCONFIG     128
 1072 #define SCO_A_GETDEV        130
 1073 
 1074 #define SCO_AD_HALT         0
 1075 #define SCO_AD_BOOT         1
 1076 #define SCO_AD_IBOOT        2
 1077 #define SCO_AD_PWRDOWN      3
 1078 #define SCO_AD_PWRNAP       4
 1079 
 1080 #define SCO_AD_PANICBOOT    1
 1081 
 1082 #define SCO_AD_GETBMAJ      0
 1083 #define SCO_AD_GETCMAJ      1
 1084 
 1085         if (suser(td))
 1086                 return EPERM;
 1087 
 1088         switch(uap->cmd) {
 1089         case SCO_A_REBOOT:
 1090         case SCO_A_SHUTDOWN:
 1091                 switch(uap->func) {
 1092                         struct reboot_args r;
 1093                 case SCO_AD_HALT:
 1094                 case SCO_AD_PWRDOWN:
 1095                 case SCO_AD_PWRNAP:
 1096                         r.opt = RB_HALT;
 1097                         reboot(td, &r);
 1098                 case SCO_AD_BOOT:
 1099                 case SCO_AD_IBOOT:
 1100                         r.opt = RB_AUTOBOOT;
 1101                         reboot(td, &r);
 1102                 }
 1103                 return EINVAL;
 1104         case SCO_A_REMOUNT:
 1105         case SCO_A_CLOCK:
 1106         case SCO_A_SETCONFIG:
 1107                 return 0;
 1108         case SCO_A_GETDEV:
 1109                 return EINVAL;  /* XXX - TODO */
 1110         }
 1111         return EINVAL;
 1112 }
 1113 
 1114 int
 1115 ibcs2_sysfs(td, uap)
 1116         struct thread *td;
 1117         struct ibcs2_sysfs_args *uap;
 1118 {
 1119 #define IBCS2_GETFSIND        1
 1120 #define IBCS2_GETFSTYP        2
 1121 #define IBCS2_GETNFSTYP       3
 1122 
 1123         switch(uap->cmd) {
 1124         case IBCS2_GETFSIND:
 1125         case IBCS2_GETFSTYP:
 1126         case IBCS2_GETNFSTYP:
 1127                 break;
 1128         }
 1129         return EINVAL;          /* XXX - TODO */
 1130 }
 1131 
 1132 int
 1133 ibcs2_unlink(td, uap)
 1134         struct thread *td;
 1135         struct ibcs2_unlink_args *uap;
 1136 {
 1137         caddr_t sg = stackgap_init();
 1138 
 1139         CHECKALTEXIST(td, &sg, uap->path);
 1140         return unlink(td, (struct unlink_args *)uap);
 1141 }
 1142 
 1143 int
 1144 ibcs2_chdir(td, uap)
 1145         struct thread *td;
 1146         struct ibcs2_chdir_args *uap;
 1147 {
 1148         caddr_t sg = stackgap_init();
 1149 
 1150         CHECKALTEXIST(td, &sg, uap->path);
 1151         return chdir(td, (struct chdir_args *)uap);
 1152 }
 1153 
 1154 int
 1155 ibcs2_chmod(td, uap)
 1156         struct thread *td;
 1157         struct ibcs2_chmod_args *uap;
 1158 {
 1159         caddr_t sg = stackgap_init();
 1160 
 1161         CHECKALTEXIST(td, &sg, uap->path);
 1162         return chmod(td, (struct chmod_args *)uap);
 1163 }
 1164 
 1165 int
 1166 ibcs2_chown(td, uap)
 1167         struct thread *td;
 1168         struct ibcs2_chown_args *uap;
 1169 {
 1170         caddr_t sg = stackgap_init();
 1171 
 1172         CHECKALTEXIST(td, &sg, uap->path);
 1173         return chown(td, (struct chown_args *)uap);
 1174 }
 1175 
 1176 int
 1177 ibcs2_rmdir(td, uap)
 1178         struct thread *td;
 1179         struct ibcs2_rmdir_args *uap;
 1180 {
 1181         caddr_t sg = stackgap_init();
 1182 
 1183         CHECKALTEXIST(td, &sg, uap->path);
 1184         return rmdir(td, (struct rmdir_args *)uap);
 1185 }
 1186 
 1187 int
 1188 ibcs2_mkdir(td, uap)
 1189         struct thread *td;
 1190         struct ibcs2_mkdir_args *uap;
 1191 {
 1192         caddr_t sg = stackgap_init();
 1193 
 1194         CHECKALTCREAT(td, &sg, uap->path);
 1195         return mkdir(td, (struct mkdir_args *)uap);
 1196 }
 1197 
 1198 int
 1199 ibcs2_symlink(td, uap)
 1200         struct thread *td;
 1201         struct ibcs2_symlink_args *uap;
 1202 {
 1203         caddr_t sg = stackgap_init();
 1204 
 1205         CHECKALTEXIST(td, &sg, uap->path);
 1206         CHECKALTCREAT(td, &sg, uap->link);
 1207         return symlink(td, (struct symlink_args *)uap);
 1208 }
 1209 
 1210 int
 1211 ibcs2_rename(td, uap)
 1212         struct thread *td;
 1213         struct ibcs2_rename_args *uap;
 1214 {
 1215         caddr_t sg = stackgap_init();
 1216 
 1217         CHECKALTEXIST(td, &sg, uap->from);
 1218         CHECKALTCREAT(td, &sg, uap->to);
 1219         return rename(td, (struct rename_args *)uap);
 1220 }
 1221 
 1222 int
 1223 ibcs2_readlink(td, uap)
 1224         struct thread *td;
 1225         struct ibcs2_readlink_args *uap;
 1226 {
 1227         caddr_t sg = stackgap_init();
 1228 
 1229         CHECKALTEXIST(td, &sg, uap->path);
 1230         return readlink(td, (struct readlink_args *) uap);
 1231 }

Cache object: 7b0ee84c0ce31c56ef667f23af0f296c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.