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

Cache object: 482f34c2ec74cbdd6f3c1f428c7ad7e5


[ 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.