root/compat/ibcs2/ibcs2_fcntl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cvt_o_flags
  2. cvt_flock2iflock
  3. cvt_iflock2flock
  4. ioflags2oflags
  5. oflags2ioflags
  6. ibcs2_sys_open
  7. ibcs2_sys_creat
  8. ibcs2_sys_access
  9. ibcs2_sys_eaccess
  10. ibcs2_sys_fcntl

    1 /*      $OpenBSD: ibcs2_fcntl.c,v 1.9 2002/03/14 01:26:50 millert Exp $ */
    2 /*      $NetBSD: ibcs2_fcntl.c,v 1.6 1996/05/03 17:05:20 christos Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1997 Theo de Raadt
    6  * Copyright (c) 1995 Scott Bartram
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/namei.h>
   35 #include <sys/proc.h>
   36 #include <sys/file.h>
   37 #include <sys/stat.h>
   38 #include <sys/filedesc.h>
   39 #include <sys/ioctl.h>
   40 #include <sys/kernel.h>
   41 #include <sys/mount.h>
   42 #include <sys/malloc.h>
   43 #include <sys/syscallargs.h>
   44 #include <sys/vnode.h>
   45 
   46 #include <compat/ibcs2/ibcs2_types.h>
   47 #include <compat/ibcs2/ibcs2_fcntl.h>
   48 #include <compat/ibcs2/ibcs2_unistd.h>
   49 #include <compat/ibcs2/ibcs2_signal.h>
   50 #include <compat/ibcs2/ibcs2_syscallargs.h>
   51 #include <compat/ibcs2/ibcs2_util.h>
   52 
   53 static int cvt_o_flags(int);
   54 static void cvt_flock2iflock(struct flock *, struct ibcs2_flock *);
   55 static void cvt_iflock2flock(struct ibcs2_flock *, struct flock *);
   56 static int ioflags2oflags(int);
   57 static int oflags2ioflags(int);
   58 
   59 static int
   60 cvt_o_flags(flags)
   61         int flags;
   62 {
   63         int r = 0;
   64 
   65         /* convert mode into NetBSD mode */
   66         if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
   67         if (flags & IBCS2_O_RDWR) r |= O_RDWR;
   68         if (flags & (IBCS2_O_NDELAY | IBCS2_O_NONBLOCK)) r |= O_NONBLOCK;
   69         if (flags & IBCS2_O_APPEND) r |= O_APPEND;
   70         if (flags & IBCS2_O_SYNC) r |= O_SYNC;
   71         if (flags & IBCS2_O_CREAT) r |= O_CREAT;
   72         if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
   73         if (flags & IBCS2_O_EXCL) r |= O_EXCL;
   74         return r;
   75 }
   76 
   77 static void
   78 cvt_flock2iflock(flp, iflp)
   79         struct flock *flp;
   80         struct ibcs2_flock *iflp;
   81 {
   82         switch (flp->l_type) {
   83         case F_RDLCK:
   84                 iflp->l_type = IBCS2_F_RDLCK;
   85                 break;
   86         case F_WRLCK:
   87                 iflp->l_type = IBCS2_F_WRLCK;
   88                 break;
   89         case F_UNLCK:
   90                 iflp->l_type = IBCS2_F_UNLCK;
   91                 break;
   92         }
   93         iflp->l_whence = (short)flp->l_whence;
   94         iflp->l_start = (ibcs2_off_t)flp->l_start;
   95         iflp->l_len = (ibcs2_off_t)flp->l_len;
   96         iflp->l_sysid = 0;
   97         iflp->l_pid = (ibcs2_pid_t)flp->l_pid;
   98 }
   99 
  100 static void
  101 cvt_iflock2flock(iflp, flp)
  102         struct ibcs2_flock *iflp;
  103         struct flock *flp;
  104 {
  105         flp->l_start = (off_t)iflp->l_start;
  106         flp->l_len = (off_t)iflp->l_len;
  107         flp->l_pid = (pid_t)iflp->l_pid;
  108         switch (iflp->l_type) {
  109         case IBCS2_F_RDLCK:
  110                 flp->l_type = F_RDLCK;
  111                 break;
  112         case IBCS2_F_WRLCK:
  113                 flp->l_type = F_WRLCK;
  114                 break;
  115         case IBCS2_F_UNLCK:
  116                 flp->l_type = F_UNLCK;
  117                 break;
  118         }
  119         flp->l_whence = iflp->l_whence;
  120 }
  121 
  122 /* convert iBCS2 mode into NetBSD mode */
  123 static int
  124 ioflags2oflags(flags)
  125         int flags;
  126 {
  127         int r = 0;
  128         
  129         if (flags & IBCS2_O_RDONLY) r |= O_RDONLY;
  130         if (flags & IBCS2_O_WRONLY) r |= O_WRONLY;
  131         if (flags & IBCS2_O_RDWR) r |= O_RDWR;
  132         if (flags & IBCS2_O_NDELAY) r |= O_NONBLOCK;
  133         if (flags & IBCS2_O_APPEND) r |= O_APPEND;
  134         if (flags & IBCS2_O_SYNC) r |= O_SYNC;
  135         if (flags & IBCS2_O_NONBLOCK) r |= O_NONBLOCK;
  136         if (flags & IBCS2_O_CREAT) r |= O_CREAT;
  137         if (flags & IBCS2_O_TRUNC) r |= O_TRUNC;
  138         if (flags & IBCS2_O_EXCL) r |= O_EXCL;
  139         if (flags & IBCS2_O_NOCTTY) r |= O_NOCTTY;
  140         return r;
  141 }
  142 
  143 /* convert NetBSD mode into iBCS2 mode */
  144 static int
  145 oflags2ioflags(flags)
  146         int flags;
  147 {
  148         int r = 0;
  149         
  150         if (flags & O_RDONLY) r |= IBCS2_O_RDONLY;
  151         if (flags & O_WRONLY) r |= IBCS2_O_WRONLY;
  152         if (flags & O_RDWR) r |= IBCS2_O_RDWR;
  153         if (flags & O_NDELAY) r |= IBCS2_O_NONBLOCK;
  154         if (flags & O_APPEND) r |= IBCS2_O_APPEND;
  155         if (flags & O_SYNC) r |= IBCS2_O_SYNC;
  156         if (flags & O_NONBLOCK) r |= IBCS2_O_NONBLOCK;
  157         if (flags & O_CREAT) r |= IBCS2_O_CREAT;
  158         if (flags & O_TRUNC) r |= IBCS2_O_TRUNC;
  159         if (flags & O_EXCL) r |= IBCS2_O_EXCL;
  160         if (flags & O_NOCTTY) r |= IBCS2_O_NOCTTY;
  161         return r;
  162 }
  163 
  164 int
  165 ibcs2_sys_open(p, v, retval)
  166         struct proc *p;
  167         void *v;
  168         register_t *retval;
  169 {
  170         struct ibcs2_sys_open_args /* {
  171                 syscallarg(char *) path;
  172                 syscallarg(int) flags;
  173                 syscallarg(int) mode;
  174         } */ *uap = v;
  175         int noctty = SCARG(uap, flags) & IBCS2_O_NOCTTY;
  176         int ret;
  177         caddr_t sg = stackgap_init(p->p_emul);
  178 
  179         SCARG(uap, flags) = cvt_o_flags(SCARG(uap, flags));
  180         if (SCARG(uap, flags) & O_CREAT)
  181                 IBCS2_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  182         else
  183                 IBCS2_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  184         ret = sys_open(p, uap, retval);
  185 
  186         if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
  187                 struct filedesc *fdp = p->p_fd;
  188                 struct file *fp;
  189 
  190                 if ((fp = fd_getfile(fdp, *retval)) == NULL)
  191                         return EBADF;
  192                 FREF(fp);
  193                 if (fp->f_type == DTYPE_VNODE)
  194                         (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
  195                 FRELE(fp);
  196         }
  197         return ret;
  198 }
  199 
  200 int
  201 ibcs2_sys_creat(p, v, retval)
  202         struct proc *p;  
  203         void *v;
  204         register_t *retval;
  205 {       
  206         struct ibcs2_sys_creat_args /* {
  207                 syscallarg(char *) path;
  208                 syscallarg(int) mode;
  209         } */ *uap = v;
  210         struct sys_open_args cup;   
  211         caddr_t sg = stackgap_init(p->p_emul);
  212 
  213         IBCS2_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  214         SCARG(&cup, path) = SCARG(uap, path);
  215         SCARG(&cup, mode) = SCARG(uap, mode);
  216         SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC;
  217         return sys_open(p, &cup, retval);
  218 }       
  219 
  220 int
  221 ibcs2_sys_access(p, v, retval)
  222         struct proc *p;
  223         void *v;
  224         register_t *retval;
  225 {
  226         struct ibcs2_sys_access_args /* {
  227                 syscallarg(char *) path;
  228                 syscallarg(int) flags;
  229         } */ *uap = v;
  230         struct sys_access_args cup;
  231         caddr_t sg = stackgap_init(p->p_emul);
  232 
  233         IBCS2_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  234         SCARG(&cup, path) = SCARG(uap, path);
  235         SCARG(&cup, flags) = SCARG(uap, flags);
  236         return sys_access(p, &cup, retval);
  237 }
  238 
  239 int
  240 ibcs2_sys_eaccess(p, v, retval)
  241         struct proc *p;
  242         void *v;
  243         register_t *retval;
  244 {
  245         register struct ibcs2_sys_eaccess_args /* {
  246                 syscallarg(char *) path;
  247                 syscallarg(int) flags;
  248         } */ *uap = v;
  249         register struct ucred *cred = p->p_ucred;
  250         register struct vnode *vp;
  251         int error, flags;
  252         struct nameidata nd;
  253         caddr_t sg = stackgap_init(p->p_emul);
  254 
  255         IBCS2_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  256 
  257         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  258             SCARG(uap, path), p);
  259         if ((error = namei(&nd)) != 0)
  260                 return error;
  261         vp = nd.ni_vp;
  262 
  263         /* Flags == 0 means only check for existence. */
  264         if (SCARG(uap, flags)) {
  265                 flags = 0;
  266                 if (SCARG(uap, flags) & IBCS2_R_OK)
  267                         flags |= VREAD;
  268                 if (SCARG(uap, flags) & IBCS2_W_OK)
  269                         flags |= VWRITE;
  270                 if (SCARG(uap, flags) & IBCS2_X_OK)
  271                         flags |= VEXEC;
  272                 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
  273                         error = VOP_ACCESS(vp, flags, cred, p);
  274         }
  275         vput(vp);
  276         return error;
  277 }
  278 
  279 int
  280 ibcs2_sys_fcntl(p, v, retval)
  281         struct proc *p;
  282         void *v;
  283         register_t *retval;
  284 {
  285         struct ibcs2_sys_fcntl_args /* {
  286                 syscallarg(int) fd;
  287                 syscallarg(int) cmd;
  288                 syscallarg(char *) arg;
  289         } */ *uap = v;
  290         int error;
  291         struct sys_fcntl_args fa;
  292         struct flock *flp;
  293         struct ibcs2_flock ifl;
  294         
  295         switch(SCARG(uap, cmd)) {
  296         case IBCS2_F_DUPFD:
  297                 SCARG(&fa, fd) = SCARG(uap, fd);
  298                 SCARG(&fa, cmd) = F_DUPFD;
  299                 SCARG(&fa, arg) = SCARG(uap, arg);
  300                 return sys_fcntl(p, &fa, retval);
  301         case IBCS2_F_GETFD:
  302                 SCARG(&fa, fd) = SCARG(uap, fd);
  303                 SCARG(&fa, cmd) = F_GETFD;
  304                 SCARG(&fa, arg) = SCARG(uap, arg);
  305                 return sys_fcntl(p, &fa, retval);
  306         case IBCS2_F_SETFD:
  307                 SCARG(&fa, fd) = SCARG(uap, fd);
  308                 SCARG(&fa, cmd) = F_SETFD;
  309                 SCARG(&fa, arg) = SCARG(uap, arg);
  310                 return sys_fcntl(p, &fa, retval);
  311         case IBCS2_F_GETFL:
  312                 SCARG(&fa, fd) = SCARG(uap, fd);
  313                 SCARG(&fa, cmd) = F_GETFL;
  314                 SCARG(&fa, arg) = SCARG(uap, arg);
  315                 error = sys_fcntl(p, &fa, retval);
  316                 if (error)
  317                         return error;
  318                 *retval = oflags2ioflags(*retval);
  319                 return error;
  320         case IBCS2_F_SETFL:
  321                 SCARG(&fa, fd) = SCARG(uap, fd);
  322                 SCARG(&fa, cmd) = F_SETFL;
  323                 SCARG(&fa, arg) = (void *)ioflags2oflags((int) SCARG(uap, arg));
  324                 return sys_fcntl(p, &fa, retval);
  325 
  326         case IBCS2_F_GETLK:
  327             {
  328                 caddr_t sg = stackgap_init(p->p_emul);
  329                 flp = stackgap_alloc(&sg, sizeof(*flp));
  330                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
  331                                ibcs2_flock_len);
  332                 if (error)
  333                         return error;
  334                 cvt_iflock2flock(&ifl, flp);
  335                 SCARG(&fa, fd) = SCARG(uap, fd);
  336                 SCARG(&fa, cmd) = F_GETLK;
  337                 SCARG(&fa, arg) = (void *)flp;
  338                 error = sys_fcntl(p, &fa, retval);
  339                 if (error)
  340                         return error;
  341                 cvt_flock2iflock(flp, &ifl);
  342                 return copyout((caddr_t)&ifl, (caddr_t)SCARG(uap, arg),
  343                                ibcs2_flock_len);
  344             }
  345 
  346         case IBCS2_F_SETLK:
  347             {
  348                 caddr_t sg = stackgap_init(p->p_emul);
  349                 flp = stackgap_alloc(&sg, sizeof(*flp));
  350                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
  351                                ibcs2_flock_len);
  352                 if (error)
  353                         return error;
  354                 cvt_iflock2flock(&ifl, flp);
  355                 SCARG(&fa, fd) = SCARG(uap, fd);
  356                 SCARG(&fa, cmd) = F_SETLK;
  357                 SCARG(&fa, arg) = (void *)flp;
  358                 return sys_fcntl(p, &fa, retval);
  359             }
  360 
  361         case IBCS2_F_SETLKW:
  362             {
  363                 caddr_t sg = stackgap_init(p->p_emul);
  364                 flp = stackgap_alloc(&sg, sizeof(*flp));
  365                 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&ifl,
  366                                ibcs2_flock_len);
  367                 if (error)
  368                         return error;
  369                 cvt_iflock2flock(&ifl, flp);
  370                 SCARG(&fa, fd) = SCARG(uap, fd);
  371                 SCARG(&fa, cmd) = F_SETLKW;
  372                 SCARG(&fa, arg) = (void *)flp;
  373                 return sys_fcntl(p, &fa, retval);
  374             }
  375         case IBCS2_F_FREESP:
  376             {
  377                 struct ibcs2_flock      ifl;
  378                 off_t                   off, cur;
  379                 caddr_t                 sg = stackgap_init(p->p_emul);
  380                 struct sys_fstat_args   ofst;
  381                 struct stat             ost;
  382                 struct sys_lseek_args   ols;
  383                 struct sys_ftruncate_args /* {
  384                         syscallarg(int) fd;
  385                         syscallarg(int) pad;
  386                         syscallarg(off_t) length;
  387                 } */ nuap;
  388 
  389                 error = copyin(SCARG(uap, arg), &ifl, sizeof ifl);
  390                 if (error)
  391                         return error;
  392 
  393                 SCARG(&ofst, fd) = SCARG(uap, fd);
  394                 SCARG(&ofst, sb) = stackgap_alloc(&sg,
  395                     sizeof(struct stat));
  396                 if ((error = sys_fstat(p, &ofst, retval)) != 0)
  397                         return error;
  398                 if ((error = copyin(SCARG(&ofst, sb), &ost,
  399                     sizeof ost)) != 0)
  400                         return error;
  401 
  402                 SCARG(&ols, fd) = SCARG(uap, fd);
  403                 SCARG(&ols, whence) = SEEK_CUR;
  404                 SCARG(&ols, offset) = 0;
  405                 if ((error = sys_lseek(p, &ols, (register_t *)&cur)) != 0)
  406                         return error;
  407 
  408                 off = (off_t)ifl.l_start;
  409                 switch (ifl.l_whence) {
  410                 case 0:
  411                         off = (off_t)ifl.l_start;
  412                         break;
  413                 case 1:
  414                         off = ost.st_size + (off_t)ifl.l_start;
  415                         break;
  416                 case 2:
  417                         off = cur - (off_t)ifl.l_start;
  418                         break;
  419                 default:
  420                         return EINVAL;
  421                 }
  422 
  423                 if (ifl.l_len != 0 && off + ifl.l_len != ost.st_size)
  424                         return EINVAL;  /* Sorry, cannot truncate in middle */
  425 
  426                 SCARG(&nuap, fd) = SCARG(uap, fd);
  427                 SCARG(&nuap, length) = off;
  428                 return (sys_ftruncate(p, &nuap, retval));
  429             }
  430         }
  431         return ENOSYS;
  432 }

/* [<][>][^][v][top][bottom][index][help] */