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

Cache object: f242324e9118c94f336382b9b40fa275


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