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.0/sys/i386/ibcs2/ibcs2_misc.c 284446 2015-06-16 13:09:18Z mjg $");
   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         error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
  346         if (error != 0)
  347                 return (error);
  348         if ((fp->f_flag & FREAD) == 0) {
  349                 fdrop(fp, td);
  350                 return (EBADF);
  351         }
  352         vp = fp->f_vnode;
  353         if (vp->v_type != VDIR) {       /* XXX  vnode readdir op should do this */
  354                 fdrop(fp, td);
  355                 return (EINVAL);
  356         }
  357 
  358         off = fp->f_offset;
  359 #define DIRBLKSIZ       512             /* XXX we used to use ufs's DIRBLKSIZ */
  360         buflen = max(DIRBLKSIZ, uap->nbytes);
  361         buflen = min(buflen, MAXBSIZE);
  362         buf = malloc(buflen, M_TEMP, M_WAITOK);
  363         vn_lock(vp, LK_SHARED | LK_RETRY);
  364 again:
  365         aiov.iov_base = buf;
  366         aiov.iov_len = buflen;
  367         auio.uio_iov = &aiov;
  368         auio.uio_iovcnt = 1;
  369         auio.uio_rw = UIO_READ;
  370         auio.uio_segflg = UIO_SYSSPACE;
  371         auio.uio_td = td;
  372         auio.uio_resid = buflen;
  373         auio.uio_offset = off;
  374 
  375         if (cookies) {
  376                 free(cookies, M_TEMP);
  377                 cookies = NULL;
  378         }
  379 
  380 #ifdef MAC
  381         error = mac_vnode_check_readdir(td->td_ucred, vp);
  382         if (error)
  383                 goto out;
  384 #endif
  385 
  386         /*
  387          * First we read into the malloc'ed buffer, then
  388          * we massage it into user space, one record at a time.
  389          */
  390         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0)
  391                 goto out;
  392         inp = buf;
  393         outp = uap->buf;
  394         resid = uap->nbytes;
  395         if ((len = buflen - auio.uio_resid) <= 0)
  396                 goto eof;
  397 
  398         cookiep = cookies;
  399 
  400         if (cookies) {
  401                 /*
  402                  * When using cookies, the vfs has the option of reading from
  403                  * a different offset than that supplied (UFS truncates the
  404                  * offset to a block boundary to make sure that it never reads
  405                  * partway through a directory entry, even if the directory
  406                  * has been compacted).
  407                  */
  408                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
  409                         len -= BSD_DIRENT(inp)->d_reclen;
  410                         inp += BSD_DIRENT(inp)->d_reclen;
  411                         cookiep++;
  412                         ncookies--;
  413                 }
  414         }
  415 
  416         for (; len > 0; len -= reclen) {
  417                 if (cookiep && ncookies == 0)
  418                         break;
  419                 reclen = BSD_DIRENT(inp)->d_reclen;
  420                 if (reclen & 3) {
  421                         printf("ibcs2_getdents: reclen=%d\n", reclen);
  422                         error = EFAULT;
  423                         goto out;
  424                 }
  425                 if (BSD_DIRENT(inp)->d_fileno == 0) {
  426                         inp += reclen;  /* it is a hole; squish it out */
  427                         if (cookiep) {
  428                                 off = *cookiep++;
  429                                 ncookies--;
  430                         } else
  431                                 off += reclen;
  432                         continue;
  433                 }
  434                 if (reclen > len || resid < IBCS2_RECLEN(reclen)) {
  435                         /* entry too big for buffer, so just stop */
  436                         outp++;
  437                         break;
  438                 }
  439                 /*
  440                  * Massage in place to make an iBCS2-shaped dirent (otherwise
  441                  * we have to worry about touching user memory outside of
  442                  * the copyout() call).
  443                  */
  444                 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno;
  445                 idb.d_off = (ibcs2_off_t)off;
  446                 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen);
  447                 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 ||
  448                     (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10,
  449                                      BSD_DIRENT(inp)->d_namlen + 1)) != 0)
  450                         goto out;
  451                 /* advance past this real entry */
  452                 if (cookiep) {
  453                         off = *cookiep++;
  454                         ncookies--;
  455                 } else
  456                         off += reclen;
  457                 inp += reclen;
  458                 /* advance output past iBCS2-shaped entry */
  459                 outp += IBCS2_RECLEN(reclen);
  460                 resid -= IBCS2_RECLEN(reclen);
  461         }
  462         /* if we squished out the whole block, try again */
  463         if (outp == uap->buf)
  464                 goto again;
  465         fp->f_offset = off;             /* update the vnode offset */
  466 eof:
  467         td->td_retval[0] = uap->nbytes - resid;
  468 out:
  469         VOP_UNLOCK(vp, 0);
  470         fdrop(fp, td);
  471         if (cookies)
  472                 free(cookies, M_TEMP);
  473         free(buf, M_TEMP);
  474         return (error);
  475 }
  476 
  477 int
  478 ibcs2_read(td, uap)
  479         struct thread *td;
  480         struct ibcs2_read_args *uap;
  481 {
  482         register struct vnode *vp;
  483         register caddr_t inp, buf;      /* BSD-format */
  484         register int len, reclen;       /* BSD-format */
  485         register caddr_t outp;          /* iBCS2-format */
  486         register int resid;             /* iBCS2-format */
  487         cap_rights_t rights;
  488         struct file *fp;
  489         struct uio auio;
  490         struct iovec aiov;
  491         struct ibcs2_direct {
  492                 ibcs2_ino_t ino;
  493                 char name[14];
  494         } idb;
  495         off_t off;                      /* true file offset */
  496         int buflen, error, eofflag, size;
  497         u_long *cookies = NULL, *cookiep;
  498         int ncookies;
  499 
  500         error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
  501         if (error != 0) {
  502                 if (error == EINVAL)
  503                         return sys_read(td, (struct read_args *)uap);
  504                 else
  505                         return error;
  506         }
  507         if ((fp->f_flag & FREAD) == 0) {
  508                 fdrop(fp, td);
  509                 return (EBADF);
  510         }
  511         vp = fp->f_vnode;
  512         if (vp->v_type != VDIR) {
  513                 fdrop(fp, td);
  514                 return sys_read(td, (struct read_args *)uap);
  515         }
  516 
  517         off = fp->f_offset;
  518 
  519         DPRINTF(("ibcs2_read: read directory\n"));
  520 
  521         buflen = max(DIRBLKSIZ, uap->nbytes);
  522         buflen = min(buflen, MAXBSIZE);
  523         buf = malloc(buflen, M_TEMP, M_WAITOK);
  524         vn_lock(vp, LK_SHARED | LK_RETRY);
  525 again:
  526         aiov.iov_base = buf;
  527         aiov.iov_len = buflen;
  528         auio.uio_iov = &aiov;
  529         auio.uio_iovcnt = 1;
  530         auio.uio_rw = UIO_READ;
  531         auio.uio_segflg = UIO_SYSSPACE;
  532         auio.uio_td = td;
  533         auio.uio_resid = buflen;
  534         auio.uio_offset = off;
  535 
  536         if (cookies) {
  537                 free(cookies, M_TEMP);
  538                 cookies = NULL;
  539         }
  540 
  541 #ifdef MAC
  542         error = mac_vnode_check_readdir(td->td_ucred, vp);
  543         if (error)
  544                 goto out;
  545 #endif
  546 
  547         /*
  548          * First we read into the malloc'ed buffer, then
  549          * we massage it into user space, one record at a time.
  550          */
  551         if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) {
  552                 DPRINTF(("VOP_READDIR failed: %d\n", error));
  553                 goto out;
  554         }
  555         inp = buf;
  556         outp = uap->buf;
  557         resid = uap->nbytes;
  558         if ((len = buflen - auio.uio_resid) <= 0)
  559                 goto eof;
  560 
  561         cookiep = cookies;
  562 
  563         if (cookies) {
  564                 /*
  565                  * When using cookies, the vfs has the option of reading from
  566                  * a different offset than that supplied (UFS truncates the
  567                  * offset to a block boundary to make sure that it never reads
  568                  * partway through a directory entry, even if the directory
  569                  * has been compacted).
  570                  */
  571                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
  572                         len -= BSD_DIRENT(inp)->d_reclen;
  573                         inp += BSD_DIRENT(inp)->d_reclen;
  574                         cookiep++;
  575                         ncookies--;
  576                 }
  577         }
  578 
  579         for (; len > 0 && resid > 0; len -= reclen) {
  580                 if (cookiep && ncookies == 0)
  581                         break;
  582                 reclen = BSD_DIRENT(inp)->d_reclen;
  583                 if (reclen & 3) {
  584                         printf("ibcs2_read: reclen=%d\n", reclen);
  585                         error = EFAULT;
  586                         goto out;
  587                 }
  588                 if (BSD_DIRENT(inp)->d_fileno == 0) {
  589                         inp += reclen;  /* it is a hole; squish it out */
  590                         if (cookiep) {
  591                                 off = *cookiep++;
  592                                 ncookies--;
  593                         } else
  594                                 off += reclen;
  595                         continue;
  596                 }
  597                 if (reclen > len || resid < sizeof(struct ibcs2_direct)) {
  598                         /* entry too big for buffer, so just stop */
  599                         outp++;
  600                         break;
  601                 }
  602                 /*
  603                  * Massage in place to make an iBCS2-shaped dirent (otherwise
  604                  * we have to worry about touching user memory outside of
  605                  * the copyout() call).
  606                  *
  607                  * TODO: if length(filename) > 14, then break filename into
  608                  * multiple entries and set inode = 0xffff except last
  609                  */
  610                 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe :
  611                         BSD_DIRENT(inp)->d_fileno;
  612                 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size);
  613                 bzero(idb.name + size, 14 - size);
  614                 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0)
  615                         goto out;
  616                 /* advance past this real entry */
  617                 if (cookiep) {
  618                         off = *cookiep++;
  619                         ncookies--;
  620                 } else
  621                         off += reclen;
  622                 inp += reclen;
  623                 /* advance output past iBCS2-shaped entry */
  624                 outp += sizeof(struct ibcs2_direct);
  625                 resid -= sizeof(struct ibcs2_direct);
  626         }
  627         /* if we squished out the whole block, try again */
  628         if (outp == uap->buf)
  629                 goto again;
  630         fp->f_offset = off;             /* update the vnode offset */
  631 eof:
  632         td->td_retval[0] = uap->nbytes - resid;
  633 out:
  634         VOP_UNLOCK(vp, 0);
  635         fdrop(fp, td);
  636         if (cookies)
  637                 free(cookies, M_TEMP);
  638         free(buf, M_TEMP);
  639         return (error);
  640 }
  641 
  642 int
  643 ibcs2_mknod(td, uap)
  644         struct thread *td;
  645         struct ibcs2_mknod_args *uap;
  646 {
  647         char *path;
  648         int error;
  649 
  650         CHECKALTCREAT(td, uap->path, &path);
  651         if (S_ISFIFO(uap->mode)) {
  652                 error = kern_mkfifoat(td, AT_FDCWD, path,
  653                     UIO_SYSSPACE, uap->mode);
  654         } else {
  655                 error = kern_mknodat(td, AT_FDCWD, path, UIO_SYSSPACE,
  656                     uap->mode, uap->dev);
  657         }
  658         free(path, M_TEMP);
  659         return (error);
  660 }
  661 
  662 int
  663 ibcs2_getgroups(td, uap)
  664         struct thread *td;
  665         struct ibcs2_getgroups_args *uap;
  666 {
  667         struct ucred *cred;
  668         ibcs2_gid_t *iset;
  669         u_int i, ngrp;
  670         int error;
  671 
  672         cred = td->td_ucred;
  673         ngrp = cred->cr_ngroups;
  674 
  675         if (uap->gidsetsize == 0) {
  676                 error = 0;
  677                 goto out;
  678         }
  679         if (uap->gidsetsize < ngrp)
  680                 return (EINVAL);
  681 
  682         iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK);
  683         for (i = 0; i < ngrp; i++)
  684                 iset[i] = (ibcs2_gid_t)cred->cr_groups[i];
  685         error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t));
  686         free(iset, M_TEMP);
  687 out:
  688         td->td_retval[0] = ngrp;
  689         return (error);
  690 }
  691 
  692 int
  693 ibcs2_setgroups(td, uap)
  694         struct thread *td;
  695         struct ibcs2_setgroups_args *uap;
  696 {
  697         ibcs2_gid_t *iset;
  698         gid_t *gp;
  699         int error, i;
  700 
  701         if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1)
  702                 return (EINVAL);
  703         if (uap->gidsetsize && uap->gidset == NULL)
  704                 return (EINVAL);
  705         gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK);
  706         if (uap->gidsetsize) {
  707                 iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK);
  708                 error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) *
  709                     uap->gidsetsize);
  710                 if (error) {
  711                         free(iset, M_TEMP);
  712                         goto out;
  713                 }
  714                 for (i = 0; i < uap->gidsetsize; i++)
  715                         gp[i] = (gid_t)iset[i];
  716         }
  717 
  718         error = kern_setgroups(td, uap->gidsetsize, gp);
  719 out:
  720         free(gp, M_TEMP);
  721         return (error);
  722 }
  723 
  724 int
  725 ibcs2_setuid(td, uap)
  726         struct thread *td;
  727         struct ibcs2_setuid_args *uap;
  728 {
  729         struct setuid_args sa;
  730 
  731         sa.uid = (uid_t)uap->uid;
  732         return sys_setuid(td, &sa);
  733 }
  734 
  735 int
  736 ibcs2_setgid(td, uap)
  737         struct thread *td;
  738         struct ibcs2_setgid_args *uap;
  739 {
  740         struct setgid_args sa;
  741 
  742         sa.gid = (gid_t)uap->gid;
  743         return sys_setgid(td, &sa);
  744 }
  745 
  746 int
  747 ibcs2_time(td, uap)
  748         struct thread *td;
  749         struct ibcs2_time_args *uap;
  750 {
  751         struct timeval tv;
  752 
  753         microtime(&tv);
  754         td->td_retval[0] = tv.tv_sec;
  755         if (uap->tp)
  756                 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp,
  757                                sizeof(ibcs2_time_t));
  758         else
  759                 return 0;
  760 }
  761 
  762 int
  763 ibcs2_pathconf(td, uap)
  764         struct thread *td;
  765         struct ibcs2_pathconf_args *uap;
  766 {
  767         char *path;
  768         int error;
  769 
  770         CHECKALTEXIST(td, uap->path, &path);
  771         uap->name++;    /* iBCS2 _PC_* defines are offset by one */
  772         error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW);
  773         free(path, M_TEMP);
  774         return (error);
  775 }
  776 
  777 int
  778 ibcs2_fpathconf(td, uap)
  779         struct thread *td;
  780         struct ibcs2_fpathconf_args *uap;
  781 {
  782         uap->name++;    /* iBCS2 _PC_* defines are offset by one */
  783         return sys_fpathconf(td, (struct fpathconf_args *)uap);
  784 }
  785 
  786 int
  787 ibcs2_sysconf(td, uap)
  788         struct thread *td;
  789         struct ibcs2_sysconf_args *uap;
  790 {
  791         int mib[2], value, len, error;
  792 
  793         switch(uap->name) {
  794         case IBCS2_SC_ARG_MAX:
  795                 mib[1] = KERN_ARGMAX;
  796                 break;
  797 
  798         case IBCS2_SC_CHILD_MAX:
  799                 td->td_retval[0] = lim_cur(td, RLIMIT_NPROC);
  800                 return 0;
  801 
  802         case IBCS2_SC_CLK_TCK:
  803                 td->td_retval[0] = hz;
  804                 return 0;
  805 
  806         case IBCS2_SC_NGROUPS_MAX:
  807                 mib[1] = KERN_NGROUPS;
  808                 break;
  809 
  810         case IBCS2_SC_OPEN_MAX:
  811                 td->td_retval[0] = lim_cur(td, RLIMIT_NOFILE);
  812                 return 0;
  813                 
  814         case IBCS2_SC_JOB_CONTROL:
  815                 mib[1] = KERN_JOB_CONTROL;
  816                 break;
  817                 
  818         case IBCS2_SC_SAVED_IDS:
  819                 mib[1] = KERN_SAVED_IDS;
  820                 break;
  821                 
  822         case IBCS2_SC_VERSION:
  823                 mib[1] = KERN_POSIX1;
  824                 break;
  825                 
  826         case IBCS2_SC_PASS_MAX:
  827                 td->td_retval[0] = 128;         /* XXX - should we create PASS_MAX ? */
  828                 return 0;
  829 
  830         case IBCS2_SC_XOPEN_VERSION:
  831                 td->td_retval[0] = 2;           /* XXX: What should that be? */
  832                 return 0;
  833                 
  834         default:
  835                 return EINVAL;
  836         }
  837 
  838         mib[0] = CTL_KERN;
  839         len = sizeof(value);
  840         error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0);
  841         if (error)
  842                 return error;
  843         td->td_retval[0] = value;
  844         return 0;
  845 }
  846 
  847 int
  848 ibcs2_alarm(td, uap)
  849         struct thread *td;
  850         struct ibcs2_alarm_args *uap;
  851 {
  852         struct itimerval itv, oitv;
  853         int error;
  854 
  855         timevalclear(&itv.it_interval);
  856         itv.it_value.tv_sec = uap->sec;
  857         itv.it_value.tv_usec = 0;
  858         error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
  859         if (error)
  860                 return (error);
  861         if (oitv.it_value.tv_usec != 0)
  862                 oitv.it_value.tv_sec++;
  863         td->td_retval[0] = oitv.it_value.tv_sec;
  864         return (0);
  865 }
  866 
  867 int
  868 ibcs2_times(td, uap)
  869         struct thread *td;
  870         struct ibcs2_times_args *uap;
  871 {
  872         struct rusage ru;
  873         struct timeval t;
  874         struct tms tms;
  875         int error;
  876 
  877 #define CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
  878 
  879         error = kern_getrusage(td, RUSAGE_SELF, &ru);
  880         if (error)
  881                 return (error);
  882         tms.tms_utime = CONVTCK(ru.ru_utime);
  883         tms.tms_stime = CONVTCK(ru.ru_stime);
  884 
  885         error = kern_getrusage(td, RUSAGE_CHILDREN, &ru);
  886         if (error)
  887                 return (error);
  888         tms.tms_cutime = CONVTCK(ru.ru_utime);
  889         tms.tms_cstime = CONVTCK(ru.ru_stime);
  890 
  891         microtime(&t);
  892         td->td_retval[0] = CONVTCK(t);
  893         
  894         return (copyout(&tms, uap->tp, sizeof(struct tms)));
  895 }
  896 
  897 int
  898 ibcs2_stime(td, uap)
  899         struct thread *td;
  900         struct ibcs2_stime_args *uap;
  901 {
  902         struct timeval tv;
  903         long secs;
  904         int error;
  905 
  906         error = copyin(uap->timep, &secs, sizeof(long));
  907         if (error)
  908                 return (error);
  909         tv.tv_sec = secs;
  910         tv.tv_usec = 0;
  911         error = kern_settimeofday(td, &tv, NULL);
  912         if (error)
  913                 error = EPERM;
  914         return (error);
  915 }
  916 
  917 int
  918 ibcs2_utime(td, uap)
  919         struct thread *td;
  920         struct ibcs2_utime_args *uap;
  921 {
  922         struct ibcs2_utimbuf ubuf;
  923         struct timeval tbuf[2], *tp;
  924         char *path;
  925         int error;
  926 
  927         if (uap->buf) {
  928                 error = copyin(uap->buf, &ubuf, sizeof(ubuf));
  929                 if (error)
  930                         return (error);
  931                 tbuf[0].tv_sec = ubuf.actime;
  932                 tbuf[0].tv_usec = 0;
  933                 tbuf[1].tv_sec = ubuf.modtime;
  934                 tbuf[1].tv_usec = 0;
  935                 tp = tbuf;
  936         } else
  937                 tp = NULL;
  938 
  939         CHECKALTEXIST(td, uap->path, &path);
  940         error = kern_utimesat(td, AT_FDCWD, path, UIO_SYSSPACE,
  941             tp, UIO_SYSSPACE);
  942         free(path, M_TEMP);
  943         return (error);
  944 }
  945 
  946 int
  947 ibcs2_nice(td, uap)
  948         struct thread *td;
  949         struct ibcs2_nice_args *uap;
  950 {
  951         int error;
  952         struct setpriority_args sa;
  953 
  954         sa.which = PRIO_PROCESS;
  955         sa.who = 0;
  956         sa.prio = td->td_proc->p_nice + uap->incr;
  957         if ((error = sys_setpriority(td, &sa)) != 0)
  958                 return EPERM;
  959         td->td_retval[0] = td->td_proc->p_nice;
  960         return 0;
  961 }
  962 
  963 /*
  964  * iBCS2 getpgrp, setpgrp, setsid, and setpgid
  965  */
  966 
  967 int
  968 ibcs2_pgrpsys(td, uap)
  969         struct thread *td;
  970         struct ibcs2_pgrpsys_args *uap;
  971 {
  972         struct proc *p = td->td_proc;
  973         switch (uap->type) {
  974         case 0:                 /* getpgrp */
  975                 PROC_LOCK(p);
  976                 td->td_retval[0] = p->p_pgrp->pg_id;
  977                 PROC_UNLOCK(p);
  978                 return 0;
  979 
  980         case 1:                 /* setpgrp */
  981             {
  982                 struct setpgid_args sa;
  983 
  984                 sa.pid = 0;
  985                 sa.pgid = 0;
  986                 sys_setpgid(td, &sa);
  987                 PROC_LOCK(p);
  988                 td->td_retval[0] = p->p_pgrp->pg_id;
  989                 PROC_UNLOCK(p);
  990                 return 0;
  991             }
  992 
  993         case 2:                 /* setpgid */
  994             {
  995                 struct setpgid_args sa;
  996 
  997                 sa.pid = uap->pid;
  998                 sa.pgid = uap->pgid;
  999                 return sys_setpgid(td, &sa);
 1000             }
 1001 
 1002         case 3:                 /* setsid */
 1003                 return sys_setsid(td, NULL);
 1004 
 1005         default:
 1006                 return EINVAL;
 1007         }
 1008 }
 1009 
 1010 /*
 1011  * XXX - need to check for nested calls
 1012  */
 1013 
 1014 int
 1015 ibcs2_plock(td, uap)
 1016         struct thread *td;
 1017         struct ibcs2_plock_args *uap;
 1018 {
 1019         int error;
 1020 #define IBCS2_UNLOCK    0
 1021 #define IBCS2_PROCLOCK  1
 1022 #define IBCS2_TEXTLOCK  2
 1023 #define IBCS2_DATALOCK  4
 1024 
 1025         
 1026         switch(uap->cmd) {
 1027         case IBCS2_UNLOCK:
 1028                 error = priv_check(td, PRIV_VM_MUNLOCK);
 1029                 if (error)
 1030                         return (error);
 1031                 /* XXX - TODO */
 1032                 return (0);
 1033 
 1034         case IBCS2_PROCLOCK:
 1035         case IBCS2_TEXTLOCK:
 1036         case IBCS2_DATALOCK:
 1037                 error = priv_check(td, PRIV_VM_MLOCK);
 1038                 if (error)
 1039                         return (error);
 1040                 /* XXX - TODO */
 1041                 return 0;
 1042         }
 1043         return EINVAL;
 1044 }
 1045 
 1046 int
 1047 ibcs2_uadmin(td, uap)
 1048         struct thread *td;
 1049         struct ibcs2_uadmin_args *uap;
 1050 {
 1051 #define SCO_A_REBOOT        1
 1052 #define SCO_A_SHUTDOWN      2
 1053 #define SCO_A_REMOUNT       4
 1054 #define SCO_A_CLOCK         8
 1055 #define SCO_A_SETCONFIG     128
 1056 #define SCO_A_GETDEV        130
 1057 
 1058 #define SCO_AD_HALT         0
 1059 #define SCO_AD_BOOT         1
 1060 #define SCO_AD_IBOOT        2
 1061 #define SCO_AD_PWRDOWN      3
 1062 #define SCO_AD_PWRNAP       4
 1063 
 1064 #define SCO_AD_PANICBOOT    1
 1065 
 1066 #define SCO_AD_GETBMAJ      0
 1067 #define SCO_AD_GETCMAJ      1
 1068 
 1069         switch(uap->cmd) {
 1070         case SCO_A_REBOOT:
 1071         case SCO_A_SHUTDOWN:
 1072                 switch(uap->func) {
 1073                         struct reboot_args r;
 1074                 case SCO_AD_HALT:
 1075                 case SCO_AD_PWRDOWN:
 1076                 case SCO_AD_PWRNAP:
 1077                         r.opt = RB_HALT;
 1078                         return (sys_reboot(td, &r));
 1079                 case SCO_AD_BOOT:
 1080                 case SCO_AD_IBOOT:
 1081                         r.opt = RB_AUTOBOOT;
 1082                         return (sys_reboot(td, &r));
 1083                 }
 1084                 return EINVAL;
 1085         case SCO_A_REMOUNT:
 1086         case SCO_A_CLOCK:
 1087         case SCO_A_SETCONFIG:
 1088                 return 0;
 1089         case SCO_A_GETDEV:
 1090                 return EINVAL;  /* XXX - TODO */
 1091         }
 1092         return EINVAL;
 1093 }
 1094 
 1095 int
 1096 ibcs2_sysfs(td, uap)
 1097         struct thread *td;
 1098         struct ibcs2_sysfs_args *uap;
 1099 {
 1100 #define IBCS2_GETFSIND        1
 1101 #define IBCS2_GETFSTYP        2
 1102 #define IBCS2_GETNFSTYP       3
 1103 
 1104         switch(uap->cmd) {
 1105         case IBCS2_GETFSIND:
 1106         case IBCS2_GETFSTYP:
 1107         case IBCS2_GETNFSTYP:
 1108                 break;
 1109         }
 1110         return EINVAL;          /* XXX - TODO */
 1111 }
 1112 
 1113 int
 1114 ibcs2_unlink(td, uap)
 1115         struct thread *td;
 1116         struct ibcs2_unlink_args *uap;
 1117 {
 1118         char *path;
 1119         int error;
 1120 
 1121         CHECKALTEXIST(td, uap->path, &path);
 1122         error = kern_unlinkat(td, AT_FDCWD, path, UIO_SYSSPACE, 0);
 1123         free(path, M_TEMP);
 1124         return (error);
 1125 }
 1126 
 1127 int
 1128 ibcs2_chdir(td, uap)
 1129         struct thread *td;
 1130         struct ibcs2_chdir_args *uap;
 1131 {
 1132         char *path;
 1133         int error;
 1134 
 1135         CHECKALTEXIST(td, uap->path, &path);
 1136         error = kern_chdir(td, path, UIO_SYSSPACE);
 1137         free(path, M_TEMP);
 1138         return (error);
 1139 }
 1140 
 1141 int
 1142 ibcs2_chmod(td, uap)
 1143         struct thread *td;
 1144         struct ibcs2_chmod_args *uap;
 1145 {
 1146         char *path;
 1147         int error;
 1148 
 1149         CHECKALTEXIST(td, uap->path, &path);
 1150         error = kern_fchmodat(td, AT_FDCWD, path, UIO_SYSSPACE, uap->mode, 0);
 1151         free(path, M_TEMP);
 1152         return (error);
 1153 }
 1154 
 1155 int
 1156 ibcs2_chown(td, uap)
 1157         struct thread *td;
 1158         struct ibcs2_chown_args *uap;
 1159 {
 1160         char *path;
 1161         int error;
 1162 
 1163         CHECKALTEXIST(td, uap->path, &path);
 1164         error = kern_fchownat(td, AT_FDCWD, path, UIO_SYSSPACE, uap->uid,
 1165             uap->gid, 0);
 1166         free(path, M_TEMP);
 1167         return (error);
 1168 }
 1169 
 1170 int
 1171 ibcs2_rmdir(td, uap)
 1172         struct thread *td;
 1173         struct ibcs2_rmdir_args *uap;
 1174 {
 1175         char *path;
 1176         int error;
 1177 
 1178         CHECKALTEXIST(td, uap->path, &path);
 1179         error = kern_rmdirat(td, AT_FDCWD, path, UIO_SYSSPACE);
 1180         free(path, M_TEMP);
 1181         return (error);
 1182 }
 1183 
 1184 int
 1185 ibcs2_mkdir(td, uap)
 1186         struct thread *td;
 1187         struct ibcs2_mkdir_args *uap;
 1188 {
 1189         char *path;
 1190         int error;
 1191 
 1192         CHECKALTEXIST(td, uap->path, &path);
 1193         error = kern_mkdirat(td, AT_FDCWD, path, UIO_SYSSPACE, uap->mode);
 1194         free(path, M_TEMP);
 1195         return (error);
 1196 }
 1197 
 1198 int
 1199 ibcs2_symlink(td, uap)
 1200         struct thread *td;
 1201         struct ibcs2_symlink_args *uap;
 1202 {
 1203         char *path, *link;
 1204         int error;
 1205 
 1206         CHECKALTEXIST(td, uap->path, &path);
 1207 
 1208         /*
 1209          * Have to expand CHECKALTCREAT() so that 'path' can be freed on
 1210          * errors.
 1211          */
 1212         error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1);
 1213         if (link == NULL) {
 1214                 free(path, M_TEMP);
 1215                 return (error);
 1216         }
 1217         error = kern_symlinkat(td, path, AT_FDCWD, link, UIO_SYSSPACE);
 1218         free(path, M_TEMP);
 1219         free(link, M_TEMP);
 1220         return (error);
 1221 }
 1222 
 1223 int
 1224 ibcs2_rename(td, uap)
 1225         struct thread *td;
 1226         struct ibcs2_rename_args *uap;
 1227 {
 1228         char *from, *to;
 1229         int error;
 1230 
 1231         CHECKALTEXIST(td, uap->from, &from);
 1232 
 1233         /*
 1234          * Have to expand CHECKALTCREAT() so that 'from' can be freed on
 1235          * errors.
 1236          */
 1237         error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1);
 1238         if (to == NULL) {
 1239                 free(from, M_TEMP);
 1240                 return (error);
 1241         }
 1242         error = kern_renameat(td, AT_FDCWD, from, AT_FDCWD, to, UIO_SYSSPACE);
 1243         free(from, M_TEMP);
 1244         free(to, M_TEMP);
 1245         return (error);
 1246 }
 1247 
 1248 int
 1249 ibcs2_readlink(td, uap)
 1250         struct thread *td;
 1251         struct ibcs2_readlink_args *uap;
 1252 {
 1253         char *path;
 1254         int error;
 1255 
 1256         CHECKALTEXIST(td, uap->path, &path);
 1257         error = kern_readlinkat(td, AT_FDCWD, path, UIO_SYSSPACE,
 1258             uap->buf, UIO_USERSPACE, uap->count);
 1259         free(path, M_TEMP);
 1260         return (error);
 1261 }

Cache object: 48293197ffaf29297acedde992d94916


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