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

Cache object: c86e671ebb2ec71f0faa3be970e2d487


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