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: releng/11.2/sys/i386/ibcs2/ibcs2_misc.c 331722 2018-03-29 02:50:57Z eadler $");
   51 
   52 /*
   53  * IBCS2 compatibility module.
   54  *
   55  * IBCS2 system calls that are implemented differently in BSD are
   56  * handled here.
   57  */
   58 #include <sys/param.h>
   59 #include <sys/systm.h>
   60 #include <sys/capsicum.h>
   61 #include <sys/dirent.h>
   62 #include <sys/fcntl.h>
   63 #include <sys/filedesc.h>
   64 #include <sys/imgact.h>
   65 #include <sys/kernel.h>
   66 #include <sys/lock.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/namei.h>
   71 #include <sys/priv.h>
   72 #include <sys/reboot.h>
   73 #include <sys/resourcevar.h>
   74 #include <sys/stat.h>
   75 #include <sys/sysctl.h>
   76 #include <sys/syscallsubr.h>
   77 #include <sys/sysproto.h>
   78 #include <sys/time.h>
   79 #include <sys/times.h>
   80 #include <sys/vnode.h>
   81 #include <sys/wait.h>
   82 
   83 #include <machine/cpu.h>
   84 
   85 #include <i386/ibcs2/ibcs2_dirent.h>
   86 #include <i386/ibcs2/ibcs2_signal.h>
   87 #include <i386/ibcs2/ibcs2_proto.h>
   88 #include <i386/ibcs2/ibcs2_unistd.h>
   89 #include <i386/ibcs2/ibcs2_util.h>
   90 #include <i386/ibcs2/ibcs2_utime.h>
   91 #include <i386/ibcs2/ibcs2_xenix.h>
   92 
   93 #include <security/mac/mac_framework.h>
   94 
   95 int
   96 ibcs2_ulimit(struct thread *td, struct ibcs2_ulimit_args *uap)
   97 {
   98         struct rlimit rl;
   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         switch (uap->cmd) {
  106         case IBCS2_GETFSIZE:
  107                 td->td_retval[0] = lim_cur(td, RLIMIT_FSIZE);
  108                 if (td->td_retval[0] == -1)
  109                         td->td_retval[0] = 0x7fffffff;
  110                 return 0;
  111         case IBCS2_SETFSIZE:
  112                 rl.rlim_max = lim_max(td, RLIMIT_FSIZE);
  113                 rl.rlim_cur = uap->newlimit;
  114                 error = kern_setrlimit(td, RLIMIT_FSIZE, &rl);
  115                 if (!error) {
  116                         td->td_retval[0] = lim_cur(td, RLIMIT_FSIZE);
  117                 } else {
  118                         DPRINTF(("failed "));
  119                 }
  120                 return error;
  121         case IBCS2_GETPSIZE:
  122                 td->td_retval[0] = lim_cur(td, RLIMIT_RSS); /* XXX */
  123                 return 0;
  124         case IBCS2_GETDTABLESIZE:
  125                 uap->cmd = IBCS2_SC_OPEN_MAX;
  126                 return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap);
  127         default:
  128                 return ENOSYS;
  129         }
  130 }
  131 
  132 #define IBCS2_WSTOPPED       0177
  133 #define IBCS2_STOPCODE(sig)  ((sig) << 8 | IBCS2_WSTOPPED)
  134 int
  135 ibcs2_wait(struct thread *td, struct ibcs2_wait_args *uap)
  136 {
  137         int error, options, status;
  138         int *statusp;
  139         pid_t pid;
  140         struct trapframe *tf = td->td_frame;
  141         
  142         if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
  143             == (PSL_Z|PSL_PF|PSL_N|PSL_V)) {
  144                 /* waitpid */
  145                 pid = uap->a1;
  146                 statusp = (int *)uap->a2;
  147                 options = uap->a3;
  148         } else {
  149                 /* wait */
  150                 pid = WAIT_ANY;
  151                 statusp = (int *)uap->a1;
  152                 options = 0;
  153         }
  154         error = kern_wait(td, pid, &status, options, NULL);
  155         if (error)
  156                 return error;
  157         if (statusp) {
  158                 /*
  159                  * Convert status/signal result.
  160                  */
  161                 if (WIFSTOPPED(status)) {
  162                         if (WSTOPSIG(status) <= 0 ||
  163                             WSTOPSIG(status) > IBCS2_SIGTBLSZ)
  164                                 return (EINVAL);
  165                         status =
  166                           IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]);
  167                 } else if (WIFSIGNALED(status)) {
  168                         if (WTERMSIG(status) <= 0 ||
  169                             WTERMSIG(status) > IBCS2_SIGTBLSZ)
  170                                 return (EINVAL);
  171                         status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))];
  172                 }
  173                 /* else exit status -- identical */
  174 
  175                 /* record result/status */
  176                 td->td_retval[1] = status;
  177                 return copyout(&status, statusp, sizeof(status));
  178         }
  179 
  180         return 0;
  181 }
  182 
  183 int
  184 ibcs2_execv(struct thread *td, struct ibcs2_execv_args *uap)
  185 {
  186         struct image_args eargs;
  187         struct vmspace *oldvmspace;
  188         char *path;
  189         int error;
  190 
  191         CHECKALTEXIST(td, uap->path, &path);
  192 
  193         error = pre_execve(td, &oldvmspace);
  194         if (error != 0) {
  195                 free(path, M_TEMP);
  196                 return (error);
  197         }
  198         error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL);
  199         free(path, M_TEMP);
  200         if (error == 0)
  201                 error = kern_execve(td, &eargs, NULL);
  202         post_execve(td, error, oldvmspace);
  203         return (error);
  204 }
  205 
  206 int
  207 ibcs2_execve(struct thread *td, struct ibcs2_execve_args *uap)
  208 {
  209         struct image_args eargs;
  210         struct vmspace *oldvmspace;
  211         char *path;
  212         int error;
  213 
  214         CHECKALTEXIST(td, uap->path, &path);
  215 
  216         error = pre_execve(td, &oldvmspace);
  217         if (error != 0) {
  218                 free(path, M_TEMP);
  219                 return (error);
  220         }
  221         error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp,
  222             uap->envp);
  223         free(path, M_TEMP);
  224         if (error == 0)
  225                 error = kern_execve(td, &eargs, NULL);
  226         post_execve(td, error, oldvmspace);
  227         return (error);
  228 }
  229 
  230 int
  231 ibcs2_umount(struct thread *td, struct ibcs2_umount_args *uap)
  232 {
  233         struct unmount_args um;
  234 
  235         um.path = uap->name;
  236         um.flags = 0;
  237         return sys_unmount(td, &um);
  238 }
  239 
  240 int
  241 ibcs2_mount(struct thread *td, struct ibcs2_mount_args *uap)
  242 {
  243 #ifdef notyet
  244         int oflags = uap->flags, nflags, error;
  245         char fsname[MFSNAMELEN];
  246 
  247         if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5))
  248                 return (EINVAL);
  249         if ((oflags & IBCS2_MS_NEWTYPE) == 0)
  250                 return (EINVAL);
  251         nflags = 0;
  252         if (oflags & IBCS2_MS_RDONLY)
  253                 nflags |= MNT_RDONLY;
  254         if (oflags & IBCS2_MS_NOSUID)
  255                 nflags |= MNT_NOSUID;
  256         if (oflags & IBCS2_MS_REMOUNT)
  257                 nflags |= MNT_UPDATE;
  258         uap->flags = nflags;
  259 
  260         if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname,
  261                               (u_int *)0))
  262                 return (error);
  263 
  264         if (strcmp(fsname, "4.2") == 0) {
  265                 uap->type = (caddr_t)STACK_ALLOC();
  266                 if (error = copyout("ufs", uap->type, sizeof("ufs")))
  267                         return (error);
  268         } else if (strcmp(fsname, "nfs") == 0) {
  269                 struct ibcs2_nfs_args sna;
  270                 struct sockaddr_in sain;
  271                 struct nfs_args na;
  272                 struct sockaddr sa;
  273 
  274                 if (error = copyin(uap->data, &sna, sizeof sna))
  275                         return (error);
  276                 if (error = copyin(sna.addr, &sain, sizeof sain))
  277                         return (error);
  278                 bcopy(&sain, &sa, sizeof sa);
  279                 sa.sa_len = sizeof(sain);
  280                 uap->data = (caddr_t)STACK_ALLOC();
  281                 na.addr = (struct sockaddr *)((int)uap->data + sizeof na);
  282                 na.sotype = SOCK_DGRAM;
  283                 na.proto = IPPROTO_UDP;
  284                 na.fh = (nfsv2fh_t *)sna.fh;
  285                 na.flags = sna.flags;
  286                 na.wsize = sna.wsize;
  287                 na.rsize = sna.rsize;
  288                 na.timeo = sna.timeo;
  289                 na.retrans = sna.retrans;
  290                 na.hostname = sna.hostname;
  291 
  292                 if (error = copyout(&sa, na.addr, sizeof sa))
  293                         return (error);
  294                 if (error = copyout(&na, uap->data, sizeof na))
  295                         return (error);
  296         }
  297         return (mount(td, uap));
  298 #else
  299         return EINVAL;
  300 #endif
  301 }
  302 
  303 /*
  304  * Read iBCS2-style directory entries.  We suck them into kernel space so
  305  * that they can be massaged before being copied out to user code.  Like
  306  * SunOS, we squish out `empty' entries.
  307  *
  308  * This is quite ugly, but what do you expect from compatibility code?
  309  */
  310 
  311 int
  312 ibcs2_getdents(struct thread *td, struct ibcs2_getdents_args *uap)
  313 {
  314         struct vnode *vp;
  315         caddr_t inp, buf;               /* BSD-format */
  316         int len, reclen;                /* BSD-format */
  317         caddr_t outp;                   /* iBCS2-format */
  318         int resid;                      /* iBCS2-format */
  319         cap_rights_t rights;
  320         struct file *fp;
  321         struct uio auio;
  322         struct iovec aiov;
  323         struct ibcs2_dirent idb;
  324         off_t off;                      /* true file offset */
  325         int buflen, error, eofflag;
  326         u_long *cookies = NULL, *cookiep;
  327         int ncookies;
  328 #define BSD_DIRENT(cp)          ((struct dirent *)(cp))
  329 #define IBCS2_RECLEN(reclen)    (reclen + sizeof(u_short))
  330 
  331         memset(&idb, 0, sizeof(idb));
  332         error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
  333         if (error != 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_SHARED | LK_RETRY);
  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_vnode_check_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);
  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(struct thread *td, struct ibcs2_read_args *uap)
  466 {
  467         struct vnode *vp;
  468         caddr_t inp, buf;               /* BSD-format */
  469         int len, reclen;                /* BSD-format */
  470         caddr_t outp;                   /* iBCS2-format */
  471         int resid;                      /* iBCS2-format */
  472         cap_rights_t rights;
  473         struct file *fp;
  474         struct uio auio;
  475         struct iovec aiov;
  476         struct ibcs2_direct {
  477                 ibcs2_ino_t ino;
  478                 char name[14];
  479         } idb;
  480         off_t off;                      /* true file offset */
  481         int buflen, error, eofflag, size;
  482         u_long *cookies = NULL, *cookiep;
  483         int ncookies;
  484 
  485         error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
  486         if (error != 0) {
  487                 if (error == EINVAL)
  488                         return sys_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 sys_read(td, (struct read_args *)uap);
  500         }
  501 
  502         off = fp->f_offset;
  503 
  504         DPRINTF(("ibcs2_read: read directory\n"));
  505 
  506         buflen = max(DIRBLKSIZ, uap->nbytes);
  507         buflen = min(buflen, MAXBSIZE);
  508         buf = malloc(buflen, M_TEMP, M_WAITOK);
  509         vn_lock(vp, LK_SHARED | LK_RETRY);
  510 again:
  511         aiov.iov_base = buf;
  512         aiov.iov_len = buflen;
  513         auio.uio_iov = &aiov;
  514         auio.uio_iovcnt = 1;
  515         auio.uio_rw = UIO_READ;
  516         auio.uio_segflg = UIO_SYSSPACE;
  517         auio.uio_td = td;
  518         auio.uio_resid = buflen;
  519         auio.uio_offset = off;
  520 
  521         if (cookies) {
  522                 free(cookies, M_TEMP);
  523                 cookies = NULL;
  524         }
  525 
  526 #ifdef MAC
  527         error = mac_vnode_check_readdir(td->td_ucred, vp);
  528         if (error)
  529                 goto out;
  530 #endif
  531 
  532         /*
  533          * First we read into the malloc'ed buffer, then
  534          * we massage it into user space, one record at a time.
  535          */
  536         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) {
  537                 DPRINTF(("VOP_READDIR failed: %d\n", error));
  538                 goto out;
  539         }
  540         inp = buf;
  541         outp = uap->buf;
  542         resid = uap->nbytes;
  543         if ((len = buflen - auio.uio_resid) <= 0)
  544                 goto eof;
  545 
  546         cookiep = cookies;
  547 
  548         if (cookies) {
  549                 /*
  550                  * When using cookies, the vfs has the option of reading from
  551                  * a different offset than that supplied (UFS truncates the
  552                  * offset to a block boundary to make sure that it never reads
  553                  * partway through a directory entry, even if the directory
  554                  * has been compacted).
  555                  */
  556                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
  557                         len -= BSD_DIRENT(inp)->d_reclen;
  558                         inp += BSD_DIRENT(inp)->d_reclen;
  559                         cookiep++;
  560                         ncookies--;
  561                 }
  562         }
  563 
  564         for (; len > 0 && resid > 0; len -= reclen) {
  565                 if (cookiep && ncookies == 0)
  566                         break;
  567                 reclen = BSD_DIRENT(inp)->d_reclen;
  568                 if (reclen & 3) {
  569                         printf("ibcs2_read: reclen=%d\n", reclen);
  570                         error = EFAULT;
  571                         goto out;
  572                 }
  573                 if (BSD_DIRENT(inp)->d_fileno == 0) {
  574                         inp += reclen;  /* it is a hole; squish it out */
  575                         if (cookiep) {
  576                                 off = *cookiep++;
  577                                 ncookies--;
  578                         } else
  579                                 off += reclen;
  580                         continue;
  581                 }
  582                 if (reclen > len || resid < sizeof(struct ibcs2_direct)) {
  583                         /* entry too big for buffer, so just stop */
  584                         outp++;
  585                         break;
  586                 }
  587                 /*
  588                  * Massage in place to make an iBCS2-shaped dirent (otherwise
  589                  * we have to worry about touching user memory outside of
  590                  * the copyout() call).
  591                  *
  592                  * TODO: if length(filename) > 14, then break filename into
  593                  * multiple entries and set inode = 0xffff except last
  594                  */
  595                 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe :
  596                         BSD_DIRENT(inp)->d_fileno;
  597                 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size);
  598                 bzero(idb.name + size, 14 - size);
  599                 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0)
  600                         goto out;
  601                 /* advance past this real entry */
  602                 if (cookiep) {
  603                         off = *cookiep++;
  604                         ncookies--;
  605                 } else
  606                         off += reclen;
  607                 inp += reclen;
  608                 /* advance output past iBCS2-shaped entry */
  609                 outp += sizeof(struct ibcs2_direct);
  610                 resid -= sizeof(struct ibcs2_direct);
  611         }
  612         /* if we squished out the whole block, try again */
  613         if (outp == uap->buf)
  614                 goto again;
  615         fp->f_offset = off;             /* update the vnode offset */
  616 eof:
  617         td->td_retval[0] = uap->nbytes - resid;
  618 out:
  619         VOP_UNLOCK(vp, 0);
  620         fdrop(fp, td);
  621         if (cookies)
  622                 free(cookies, M_TEMP);
  623         free(buf, M_TEMP);
  624         return (error);
  625 }
  626 
  627 int
  628 ibcs2_mknod(struct thread *td, struct ibcs2_mknod_args *uap)
  629 {
  630         char *path;
  631         int error;
  632 
  633         CHECKALTCREAT(td, uap->path, &path);
  634         if (S_ISFIFO(uap->mode)) {
  635                 error = kern_mkfifoat(td, AT_FDCWD, path,
  636                     UIO_SYSSPACE, uap->mode);
  637         } else {
  638                 error = kern_mknodat(td, AT_FDCWD, path, UIO_SYSSPACE,
  639                     uap->mode, uap->dev);
  640         }
  641         free(path, M_TEMP);
  642         return (error);
  643 }
  644 
  645 int
  646 ibcs2_getgroups(struct thread *td, struct ibcs2_getgroups_args *uap)
  647 {
  648         struct ucred *cred;
  649         ibcs2_gid_t *iset;
  650         u_int i, ngrp;
  651         int error;
  652 
  653         cred = td->td_ucred;
  654         ngrp = cred->cr_ngroups;
  655 
  656         if (uap->gidsetsize == 0) {
  657                 error = 0;
  658                 goto out;
  659         }
  660         if (uap->gidsetsize < ngrp)
  661                 return (EINVAL);
  662 
  663         iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK);
  664         for (i = 0; i < ngrp; i++)
  665                 iset[i] = (ibcs2_gid_t)cred->cr_groups[i];
  666         error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t));
  667         free(iset, M_TEMP);
  668 out:
  669         td->td_retval[0] = ngrp;
  670         return (error);
  671 }
  672 
  673 int
  674 ibcs2_setgroups(struct thread *td, struct ibcs2_setgroups_args *uap)
  675 {
  676         ibcs2_gid_t *iset;
  677         gid_t *gp;
  678         int error, i;
  679 
  680         if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1)
  681                 return (EINVAL);
  682         if (uap->gidsetsize && uap->gidset == NULL)
  683                 return (EINVAL);
  684         gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK);
  685         if (uap->gidsetsize) {
  686                 iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK);
  687                 error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) *
  688                     uap->gidsetsize);
  689                 if (error) {
  690                         free(iset, M_TEMP);
  691                         goto out;
  692                 }
  693                 for (i = 0; i < uap->gidsetsize; i++)
  694                         gp[i] = (gid_t)iset[i];
  695         }
  696 
  697         error = kern_setgroups(td, uap->gidsetsize, gp);
  698 out:
  699         free(gp, M_TEMP);
  700         return (error);
  701 }
  702 
  703 int
  704 ibcs2_setuid(struct thread *td, struct ibcs2_setuid_args *uap)
  705 {
  706         struct setuid_args sa;
  707 
  708         sa.uid = (uid_t)uap->uid;
  709         return sys_setuid(td, &sa);
  710 }
  711 
  712 int
  713 ibcs2_setgid(struct thread *td, struct ibcs2_setgid_args *uap)
  714 {
  715         struct setgid_args sa;
  716 
  717         sa.gid = (gid_t)uap->gid;
  718         return sys_setgid(td, &sa);
  719 }
  720 
  721 int
  722 ibcs2_time(struct thread *td, 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(struct thread *td, struct ibcs2_pathconf_args *uap)
  737 {
  738         char *path;
  739         int error;
  740 
  741         CHECKALTEXIST(td, uap->path, &path);
  742         uap->name++;    /* iBCS2 _PC_* defines are offset by one */
  743         error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW);
  744         free(path, M_TEMP);
  745         return (error);
  746 }
  747 
  748 int
  749 ibcs2_fpathconf(struct thread *td, struct ibcs2_fpathconf_args *uap)
  750 {
  751         uap->name++;    /* iBCS2 _PC_* defines are offset by one */
  752         return sys_fpathconf(td, (struct fpathconf_args *)uap);
  753 }
  754 
  755 int
  756 ibcs2_sysconf(struct thread *td, struct ibcs2_sysconf_args *uap)
  757 {
  758         int mib[2], value, len, error;
  759 
  760         switch(uap->name) {
  761         case IBCS2_SC_ARG_MAX:
  762                 mib[1] = KERN_ARGMAX;
  763                 break;
  764 
  765         case IBCS2_SC_CHILD_MAX:
  766                 td->td_retval[0] = lim_cur(td, RLIMIT_NPROC);
  767                 return 0;
  768 
  769         case IBCS2_SC_CLK_TCK:
  770                 td->td_retval[0] = hz;
  771                 return 0;
  772 
  773         case IBCS2_SC_NGROUPS_MAX:
  774                 mib[1] = KERN_NGROUPS;
  775                 break;
  776 
  777         case IBCS2_SC_OPEN_MAX:
  778                 td->td_retval[0] = lim_cur(td, RLIMIT_NOFILE);
  779                 return 0;
  780                 
  781         case IBCS2_SC_JOB_CONTROL:
  782                 mib[1] = KERN_JOB_CONTROL;
  783                 break;
  784                 
  785         case IBCS2_SC_SAVED_IDS:
  786                 mib[1] = KERN_SAVED_IDS;
  787                 break;
  788                 
  789         case IBCS2_SC_VERSION:
  790                 mib[1] = KERN_POSIX1;
  791                 break;
  792                 
  793         case IBCS2_SC_PASS_MAX:
  794                 td->td_retval[0] = 128;         /* XXX - should we create PASS_MAX ? */
  795                 return 0;
  796 
  797         case IBCS2_SC_XOPEN_VERSION:
  798                 td->td_retval[0] = 2;           /* XXX: What should that be? */
  799                 return 0;
  800                 
  801         default:
  802                 return EINVAL;
  803         }
  804 
  805         mib[0] = CTL_KERN;
  806         len = sizeof(value);
  807         error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0);
  808         if (error)
  809                 return error;
  810         td->td_retval[0] = value;
  811         return 0;
  812 }
  813 
  814 int
  815 ibcs2_alarm(struct thread *td, struct ibcs2_alarm_args *uap)
  816 {
  817         struct itimerval itv, oitv;
  818         int error;
  819 
  820         timevalclear(&itv.it_interval);
  821         itv.it_value.tv_sec = uap->sec;
  822         itv.it_value.tv_usec = 0;
  823         error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
  824         if (error)
  825                 return (error);
  826         if (oitv.it_value.tv_usec != 0)
  827                 oitv.it_value.tv_sec++;
  828         td->td_retval[0] = oitv.it_value.tv_sec;
  829         return (0);
  830 }
  831 
  832 int
  833 ibcs2_times(struct thread *td, struct ibcs2_times_args *uap)
  834 {
  835         struct rusage ru;
  836         struct timeval t;
  837         struct tms tms;
  838         int error;
  839 
  840 #define CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
  841 
  842         error = kern_getrusage(td, RUSAGE_SELF, &ru);
  843         if (error)
  844                 return (error);
  845         tms.tms_utime = CONVTCK(ru.ru_utime);
  846         tms.tms_stime = CONVTCK(ru.ru_stime);
  847 
  848         error = kern_getrusage(td, RUSAGE_CHILDREN, &ru);
  849         if (error)
  850                 return (error);
  851         tms.tms_cutime = CONVTCK(ru.ru_utime);
  852         tms.tms_cstime = CONVTCK(ru.ru_stime);
  853 
  854         microtime(&t);
  855         td->td_retval[0] = CONVTCK(t);
  856         
  857         return (copyout(&tms, uap->tp, sizeof(struct tms)));
  858 }
  859 
  860 int
  861 ibcs2_stime(struct thread *td, struct ibcs2_stime_args *uap)
  862 {
  863         struct timeval tv;
  864         long secs;
  865         int error;
  866 
  867         error = copyin(uap->timep, &secs, sizeof(long));
  868         if (error)
  869                 return (error);
  870         tv.tv_sec = secs;
  871         tv.tv_usec = 0;
  872         error = kern_settimeofday(td, &tv, NULL);
  873         if (error)
  874                 error = EPERM;
  875         return (error);
  876 }
  877 
  878 int
  879 ibcs2_utime(struct thread *td, struct ibcs2_utime_args *uap)
  880 {
  881         struct ibcs2_utimbuf ubuf;
  882         struct timeval tbuf[2], *tp;
  883         char *path;
  884         int error;
  885 
  886         if (uap->buf) {
  887                 error = copyin(uap->buf, &ubuf, sizeof(ubuf));
  888                 if (error)
  889                         return (error);
  890                 tbuf[0].tv_sec = ubuf.actime;
  891                 tbuf[0].tv_usec = 0;
  892                 tbuf[1].tv_sec = ubuf.modtime;
  893                 tbuf[1].tv_usec = 0;
  894                 tp = tbuf;
  895         } else
  896                 tp = NULL;
  897 
  898         CHECKALTEXIST(td, uap->path, &path);
  899         error = kern_utimesat(td, AT_FDCWD, path, UIO_SYSSPACE,
  900             tp, UIO_SYSSPACE);
  901         free(path, M_TEMP);
  902         return (error);
  903 }
  904 
  905 int
  906 ibcs2_nice(struct thread *td, struct ibcs2_nice_args *uap)
  907 {
  908         int error;
  909         struct setpriority_args sa;
  910 
  911         sa.which = PRIO_PROCESS;
  912         sa.who = 0;
  913         sa.prio = td->td_proc->p_nice + uap->incr;
  914         if ((error = sys_setpriority(td, &sa)) != 0)
  915                 return EPERM;
  916         td->td_retval[0] = td->td_proc->p_nice;
  917         return 0;
  918 }
  919 
  920 /*
  921  * iBCS2 getpgrp, setpgrp, setsid, and setpgid
  922  */
  923 
  924 int
  925 ibcs2_pgrpsys(struct thread *td, struct ibcs2_pgrpsys_args *uap)
  926 {
  927         struct proc *p = td->td_proc;
  928         switch (uap->type) {
  929         case 0:                 /* getpgrp */
  930                 PROC_LOCK(p);
  931                 td->td_retval[0] = p->p_pgrp->pg_id;
  932                 PROC_UNLOCK(p);
  933                 return 0;
  934 
  935         case 1:                 /* setpgrp */
  936             {
  937                 struct setpgid_args sa;
  938 
  939                 sa.pid = 0;
  940                 sa.pgid = 0;
  941                 sys_setpgid(td, &sa);
  942                 PROC_LOCK(p);
  943                 td->td_retval[0] = p->p_pgrp->pg_id;
  944                 PROC_UNLOCK(p);
  945                 return 0;
  946             }
  947 
  948         case 2:                 /* setpgid */
  949             {
  950                 struct setpgid_args sa;
  951 
  952                 sa.pid = uap->pid;
  953                 sa.pgid = uap->pgid;
  954                 return sys_setpgid(td, &sa);
  955             }
  956 
  957         case 3:                 /* setsid */
  958                 return sys_setsid(td, NULL);
  959 
  960         default:
  961                 return EINVAL;
  962         }
  963 }
  964 
  965 /*
  966  * XXX - need to check for nested calls
  967  */
  968 
  969 int
  970 ibcs2_plock(struct thread *td, struct ibcs2_plock_args *uap)
  971 {
  972         int error;
  973 #define IBCS2_UNLOCK    0
  974 #define IBCS2_PROCLOCK  1
  975 #define IBCS2_TEXTLOCK  2
  976 #define IBCS2_DATALOCK  4
  977 
  978         
  979         switch(uap->cmd) {
  980         case IBCS2_UNLOCK:
  981                 error = priv_check(td, PRIV_VM_MUNLOCK);
  982                 if (error)
  983                         return (error);
  984                 /* XXX - TODO */
  985                 return (0);
  986 
  987         case IBCS2_PROCLOCK:
  988         case IBCS2_TEXTLOCK:
  989         case IBCS2_DATALOCK:
  990                 error = priv_check(td, PRIV_VM_MLOCK);
  991                 if (error)
  992                         return (error);
  993                 /* XXX - TODO */
  994                 return 0;
  995         }
  996         return EINVAL;
  997 }
  998 
  999 int
 1000 ibcs2_uadmin(struct thread *td, struct ibcs2_uadmin_args *uap)
 1001 {
 1002 #define SCO_A_REBOOT        1
 1003 #define SCO_A_SHUTDOWN      2
 1004 #define SCO_A_REMOUNT       4
 1005 #define SCO_A_CLOCK         8
 1006 #define SCO_A_SETCONFIG     128
 1007 #define SCO_A_GETDEV        130
 1008 
 1009 #define SCO_AD_HALT         0
 1010 #define SCO_AD_BOOT         1
 1011 #define SCO_AD_IBOOT        2
 1012 #define SCO_AD_PWRDOWN      3
 1013 #define SCO_AD_PWRNAP       4
 1014 
 1015 #define SCO_AD_PANICBOOT    1
 1016 
 1017 #define SCO_AD_GETBMAJ      0
 1018 #define SCO_AD_GETCMAJ      1
 1019 
 1020         switch(uap->cmd) {
 1021         case SCO_A_REBOOT:
 1022         case SCO_A_SHUTDOWN:
 1023                 switch(uap->func) {
 1024                         struct reboot_args r;
 1025                 case SCO_AD_HALT:
 1026                 case SCO_AD_PWRDOWN:
 1027                 case SCO_AD_PWRNAP:
 1028                         r.opt = RB_HALT;
 1029                         return (sys_reboot(td, &r));
 1030                 case SCO_AD_BOOT:
 1031                 case SCO_AD_IBOOT:
 1032                         r.opt = RB_AUTOBOOT;
 1033                         return (sys_reboot(td, &r));
 1034                 }
 1035                 return EINVAL;
 1036         case SCO_A_REMOUNT:
 1037         case SCO_A_CLOCK:
 1038         case SCO_A_SETCONFIG:
 1039                 return 0;
 1040         case SCO_A_GETDEV:
 1041                 return EINVAL;  /* XXX - TODO */
 1042         }
 1043         return EINVAL;
 1044 }
 1045 
 1046 int
 1047 ibcs2_sysfs(struct thread *td, struct ibcs2_sysfs_args *uap)
 1048 {
 1049 #define IBCS2_GETFSIND        1
 1050 #define IBCS2_GETFSTYP        2
 1051 #define IBCS2_GETNFSTYP       3
 1052 
 1053         switch(uap->cmd) {
 1054         case IBCS2_GETFSIND:
 1055         case IBCS2_GETFSTYP:
 1056         case IBCS2_GETNFSTYP:
 1057                 break;
 1058         }
 1059         return EINVAL;          /* XXX - TODO */
 1060 }
 1061 
 1062 int
 1063 ibcs2_unlink(struct thread *td, struct ibcs2_unlink_args *uap)
 1064 {
 1065         char *path;
 1066         int error;
 1067 
 1068         CHECKALTEXIST(td, uap->path, &path);
 1069         error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0);
 1070         free(path, M_TEMP);
 1071         return (error);
 1072 }
 1073 
 1074 int
 1075 ibcs2_chdir(struct thread *td, struct ibcs2_chdir_args *uap)
 1076 {
 1077         char *path;
 1078         int error;
 1079 
 1080         CHECKALTEXIST(td, uap->path, &path);
 1081         error = kern_chdir(td, path, UIO_SYSSPACE);
 1082         free(path, M_TEMP);
 1083         return (error);
 1084 }
 1085 
 1086 int
 1087 ibcs2_chmod(struct thread *td, struct ibcs2_chmod_args *uap)
 1088 {
 1089         char *path;
 1090         int error;
 1091 
 1092         CHECKALTEXIST(td, uap->path, &path);
 1093         error = kern_fchmodat(td, AT_FDCWD, path, UIO_SYSSPACE, uap->mode, 0);
 1094         free(path, M_TEMP);
 1095         return (error);
 1096 }
 1097 
 1098 int
 1099 ibcs2_chown(struct thread *td, struct ibcs2_chown_args *uap)
 1100 {
 1101         char *path;
 1102         int error;
 1103 
 1104         CHECKALTEXIST(td, uap->path, &path);
 1105         error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, uap->uid,
 1106             uap->gid, 0);
 1107         free(path, M_TEMP);
 1108         return (error);
 1109 }
 1110 
 1111 int
 1112 ibcs2_rmdir(struct thread *td, struct ibcs2_rmdir_args *uap)
 1113 {
 1114         char *path;
 1115         int error;
 1116 
 1117         CHECKALTEXIST(td, uap->path, &path);
 1118         error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE);
 1119         free(path, M_TEMP);
 1120         return (error);
 1121 }
 1122 
 1123 int
 1124 ibcs2_mkdir(struct thread *td, struct ibcs2_mkdir_args *uap)
 1125 {
 1126         char *path;
 1127         int error;
 1128 
 1129         CHECKALTEXIST(td, uap->path, &path);
 1130         error = kern_mkdirat(td, AT_FDCWD, path, UIO_SYSSPACE, uap->mode);
 1131         free(path, M_TEMP);
 1132         return (error);
 1133 }
 1134 
 1135 int
 1136 ibcs2_symlink(struct thread *td, struct ibcs2_symlink_args *uap)
 1137 {
 1138         char *path, *link;
 1139         int error;
 1140 
 1141         CHECKALTEXIST(td, uap->path, &path);
 1142 
 1143         /*
 1144          * Have to expand CHECKALTCREAT() so that 'path' can be freed on
 1145          * errors.
 1146          */
 1147         error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1);
 1148         if (link == NULL) {
 1149                 free(path, M_TEMP);
 1150                 return (error);
 1151         }
 1152         error = kern_symlinkat(td, path, AT_FDCWD, link, UIO_SYSSPACE);
 1153         free(path, M_TEMP);
 1154         free(link, M_TEMP);
 1155         return (error);
 1156 }
 1157 
 1158 int
 1159 ibcs2_rename(struct thread *td, struct ibcs2_rename_args *uap)
 1160 {
 1161         char *from, *to;
 1162         int error;
 1163 
 1164         CHECKALTEXIST(td, uap->from, &from);
 1165 
 1166         /*
 1167          * Have to expand CHECKALTCREAT() so that 'from' can be freed on
 1168          * errors.
 1169          */
 1170         error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1);
 1171         if (to == NULL) {
 1172                 free(from, M_TEMP);
 1173                 return (error);
 1174         }
 1175         error = kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, UIO_SYSSPACE);
 1176         free(from, M_TEMP);
 1177         free(to, M_TEMP);
 1178         return (error);
 1179 }
 1180 
 1181 int
 1182 ibcs2_readlink(struct thread *td, struct ibcs2_readlink_args *uap)
 1183 {
 1184         char *path;
 1185         int error;
 1186 
 1187         CHECKALTEXIST(td, uap->path, &path);
 1188         error = kern_readlinkat(td, AT_FDCWD, path, UIO_SYSSPACE,
 1189             uap->buf, UIO_USERSPACE, uap->count);
 1190         free(path, M_TEMP);
 1191         return (error);
 1192 }

Cache object: 623cecbf599da310a96bf3ad2f6010ef


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