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

Cache object: b745046cdea420f272e6a798cdd5a863


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