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

Cache object: a3d405ceb0f632e40945d550b9028606


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