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

Cache object: 5ce85d3a107d8cb83b98e4a8f4c7cfc6


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