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/compat/linux/common/linux_file.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 /*      $NetBSD: linux_file.c,v 1.62.2.1 2004/08/15 14:23:45 tron Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Frank van der Linden and Eric Haszlakiewicz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Functions in multiarch:
   41  *      linux_sys_llseek        : linux_llseek.c
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __KERNEL_RCSID(0, "$NetBSD: linux_file.c,v 1.62.2.1 2004/08/15 14:23:45 tron Exp $");
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/namei.h>
   50 #include <sys/proc.h>
   51 #include <sys/file.h>
   52 #include <sys/stat.h>
   53 #include <sys/filedesc.h>
   54 #include <sys/ioctl.h>
   55 #include <sys/kernel.h>
   56 #include <sys/mount.h>
   57 #include <sys/malloc.h>
   58 #include <sys/vnode.h>
   59 #include <sys/tty.h>
   60 #include <sys/socketvar.h>
   61 #include <sys/conf.h>
   62 #include <sys/pipe.h>
   63 
   64 #include <sys/sa.h>
   65 #include <sys/syscallargs.h>
   66 
   67 #include <compat/linux/common/linux_types.h>
   68 #include <compat/linux/common/linux_signal.h>
   69 #include <compat/linux/common/linux_fcntl.h>
   70 #include <compat/linux/common/linux_util.h>
   71 #include <compat/linux/common/linux_machdep.h>
   72 
   73 #include <compat/linux/linux_syscallargs.h>
   74 
   75 static int linux_to_bsd_ioflags __P((int));
   76 static int bsd_to_linux_ioflags __P((int));
   77 static void bsd_to_linux_flock __P((struct flock *, struct linux_flock *));
   78 static void linux_to_bsd_flock __P((struct linux_flock *, struct flock *));
   79 static void bsd_to_linux_stat __P((struct stat *, struct linux_stat *));
   80 static int linux_stat1 __P((struct lwp *, void *, register_t *, int));
   81 
   82 /*
   83  * Some file-related calls are handled here. The usual flag conversion
   84  * an structure conversion is done, and alternate emul path searching.
   85  */
   86 
   87 /*
   88  * The next two functions convert between the Linux and NetBSD values
   89  * of the flags used in open(2) and fcntl(2).
   90  */
   91 static int
   92 linux_to_bsd_ioflags(lflags)
   93         int lflags;
   94 {
   95         int res = 0;
   96 
   97         res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
   98         res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
   99         res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
  100         res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
  101         res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
  102         res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
  103         res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
  104         res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
  105         res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC);
  106         res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
  107         res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
  108 
  109         return res;
  110 }
  111 
  112 static int
  113 bsd_to_linux_ioflags(bflags)
  114         int bflags;
  115 {
  116         int res = 0;
  117 
  118         res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
  119         res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
  120         res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
  121         res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
  122         res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
  123         res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
  124         res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
  125         res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
  126         res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC);
  127         res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
  128         res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
  129 
  130         return res;
  131 }
  132 
  133 /*
  134  * creat(2) is an obsolete function, but it's present as a Linux
  135  * system call, so let's deal with it.
  136  *
  137  * Note: On the Alpha this doesn't really exist in Linux, but it's defined
  138  * in syscalls.master anyway so this doesn't have to be special cased.
  139  *
  140  * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
  141  */
  142 int
  143 linux_sys_creat(l, v, retval)
  144         struct lwp *l;
  145         void *v;
  146         register_t *retval;
  147 {
  148         struct linux_sys_creat_args /* {
  149                 syscallarg(const char *) path;
  150                 syscallarg(int) mode;
  151         } */ *uap = v;
  152         struct proc *p = l->l_proc;
  153         struct sys_open_args oa;
  154         caddr_t sg;
  155 
  156         sg = stackgap_init(p, 0);
  157         CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  158 
  159         SCARG(&oa, path) = SCARG(uap, path);
  160         SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
  161         SCARG(&oa, mode) = SCARG(uap, mode);
  162 
  163         return sys_open(l, &oa, retval);
  164 }
  165 
  166 /*
  167  * open(2). Take care of the different flag values, and let the
  168  * NetBSD syscall do the real work. See if this operation
  169  * gives the current process a controlling terminal.
  170  * (XXX is this necessary?)
  171  */
  172 int
  173 linux_sys_open(l, v, retval)
  174         struct lwp *l;
  175         void *v;
  176         register_t *retval;
  177 {
  178         struct linux_sys_open_args /* {
  179                 syscallarg(const char *) path;
  180                 syscallarg(int) flags;
  181                 syscallarg(int) mode;
  182         } */ *uap = v;
  183         struct proc *p = l->l_proc;
  184         int error, fl;
  185         struct sys_open_args boa;
  186         caddr_t sg;
  187 
  188         sg = stackgap_init(p, 0);
  189 
  190         fl = linux_to_bsd_ioflags(SCARG(uap, flags));
  191 
  192         if (fl & O_CREAT)
  193                 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  194         else
  195                 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  196 
  197         SCARG(&boa, path) = SCARG(uap, path);
  198         SCARG(&boa, flags) = fl;
  199         SCARG(&boa, mode) = SCARG(uap, mode);
  200 
  201         if ((error = sys_open(l, &boa, retval)))
  202                 return error;
  203 
  204         /*
  205          * this bit from sunos_misc.c (and svr4_fcntl.c).
  206          * If we are a session leader, and we don't have a controlling
  207          * terminal yet, and the O_NOCTTY flag is not set, try to make
  208          * this the controlling terminal.
  209          */ 
  210         if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
  211                 struct filedesc *fdp = p->p_fd;
  212                 struct file     *fp;
  213 
  214                 fp = fd_getfile(fdp, *retval);
  215 
  216                 /* ignore any error, just give it a try */
  217                 if (fp != NULL) {
  218                         FILE_USE(fp);
  219                         if (fp->f_type == DTYPE_VNODE) {
  220                                 (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY,
  221                                     (caddr_t) 0, p);
  222                         }
  223                         FILE_UNUSE(fp, p);
  224                 }
  225         }
  226         return 0;
  227 }
  228 
  229 /*
  230  * The next two functions take care of converting the flock
  231  * structure back and forth between Linux and NetBSD format.
  232  * The only difference in the structures is the order of
  233  * the fields, and the 'whence' value.
  234  */
  235 static void
  236 bsd_to_linux_flock(bfp, lfp)
  237         struct flock *bfp;
  238         struct linux_flock *lfp;
  239 {
  240 
  241         lfp->l_start = bfp->l_start;
  242         lfp->l_len = bfp->l_len;
  243         lfp->l_pid = bfp->l_pid;
  244         lfp->l_whence = bfp->l_whence;
  245         switch (bfp->l_type) {
  246         case F_RDLCK:
  247                 lfp->l_type = LINUX_F_RDLCK;
  248                 break;
  249         case F_UNLCK:
  250                 lfp->l_type = LINUX_F_UNLCK;
  251                 break;
  252         case F_WRLCK:
  253                 lfp->l_type = LINUX_F_WRLCK;
  254                 break;
  255         }
  256 }
  257 
  258 static void
  259 linux_to_bsd_flock(lfp, bfp)
  260         struct linux_flock *lfp;
  261         struct flock *bfp;
  262 {
  263 
  264         bfp->l_start = lfp->l_start;
  265         bfp->l_len = lfp->l_len;
  266         bfp->l_pid = lfp->l_pid;
  267         bfp->l_whence = lfp->l_whence;
  268         switch (lfp->l_type) {
  269         case LINUX_F_RDLCK:
  270                 bfp->l_type = F_RDLCK;
  271                 break;
  272         case LINUX_F_UNLCK:
  273                 bfp->l_type = F_UNLCK;
  274                 break;
  275         case LINUX_F_WRLCK:
  276                 bfp->l_type = F_WRLCK;
  277                 break;
  278         }
  279 }
  280 
  281 /*
  282  * Most actions in the fcntl() call are straightforward; simply
  283  * pass control to the NetBSD system call. A few commands need
  284  * conversions after the actual system call has done its work,
  285  * because the flag values and lock structure are different.
  286  */
  287 int
  288 linux_sys_fcntl(l, v, retval)
  289         struct lwp *l;
  290         void *v;
  291         register_t *retval;
  292 {
  293         struct linux_sys_fcntl_args /* {
  294                 syscallarg(int) fd;
  295                 syscallarg(int) cmd;
  296                 syscallarg(void *) arg;
  297         } */ *uap = v;
  298         struct proc *p = l->l_proc;
  299         int fd, cmd, error;
  300         u_long val;
  301         caddr_t arg, sg;
  302         struct linux_flock lfl;
  303         struct flock *bfp, bfl;
  304         struct sys_fcntl_args fca;
  305         struct filedesc *fdp;
  306         struct file *fp;
  307         struct vnode *vp;
  308         struct vattr va;
  309         const struct cdevsw *cdev;
  310         long pgid;
  311         struct pgrp *pgrp;
  312         struct tty *tp, *(*d_tty) __P((dev_t));
  313 
  314         fd = SCARG(uap, fd);
  315         cmd = SCARG(uap, cmd);
  316         arg = (caddr_t) SCARG(uap, arg);
  317 
  318         switch (cmd) {
  319         case LINUX_F_DUPFD:
  320                 cmd = F_DUPFD;
  321                 break;
  322         case LINUX_F_GETFD:
  323                 cmd = F_GETFD;
  324                 break;
  325         case LINUX_F_SETFD:
  326                 cmd = F_SETFD;
  327                 break;
  328         case LINUX_F_GETFL:
  329                 SCARG(&fca, fd) = fd;
  330                 SCARG(&fca, cmd) = F_GETFL;
  331                 SCARG(&fca, arg) = arg;
  332                 if ((error = sys_fcntl(l, &fca, retval)))
  333                         return error;
  334                 retval[0] = bsd_to_linux_ioflags(retval[0]);
  335                 return 0;
  336         case LINUX_F_SETFL: {
  337                 struct file     *fp = NULL;
  338 
  339                 val = linux_to_bsd_ioflags((unsigned long)SCARG(uap, arg));
  340                 /*
  341                  * Linux seems to have same semantics for sending SIGIO to the
  342                  * read side of socket, but slighly different semantics
  343                  * for SIGIO to the write side.  Rather than sending the SIGIO
  344                  * every time it's possible to write (directly) more data, it
  345                  * only sends SIGIO if last write(2) failed due to insufficient
  346                  * memory to hold the data. This is compatible enough
  347                  * with NetBSD semantics to not do anything about the
  348                  * difference.
  349                  * 
  350                  * Linux does NOT send SIGIO for pipes. Deal with socketpair
  351                  * ones and DTYPE_PIPE ones. For these, we don't set
  352                  * the underlying flags (we don't pass O_ASYNC flag down
  353                  * to sys_fcntl()), but set the FASYNC flag for file descriptor,
  354                  * so that F_GETFL would report the ASYNC i/o is on.
  355                  */
  356                 if (val & O_ASYNC) {
  357                         if (((fp = fd_getfile(p->p_fd, fd)) == NULL))
  358                             return (EBADF);
  359 
  360                         FILE_USE(fp);
  361 
  362                         if (((fp->f_type == DTYPE_SOCKET) && fp->f_data
  363                               && ((struct socket *)fp->f_data)->so_state & SS_ISAPIPE)
  364                             || (fp->f_type == DTYPE_PIPE))
  365                                 val &= ~O_ASYNC;
  366                         else {
  367                                 /* not a pipe, do not modify anything */
  368                                 FILE_UNUSE(fp, p);
  369                                 fp = NULL;
  370                         }
  371                 }
  372 
  373                 SCARG(&fca, fd) = fd;
  374                 SCARG(&fca, cmd) = F_SETFL;
  375                 SCARG(&fca, arg) = (caddr_t) val;
  376 
  377                 error = sys_fcntl(l, &fca, retval);
  378 
  379                 /* Now set the FASYNC flag for pipes */
  380                 if (fp) {
  381                         if (!error)
  382                                 fp->f_flag |= FASYNC;
  383                         FILE_UNUSE(fp, p);
  384                 }
  385 
  386                 return (error);
  387             }
  388         case LINUX_F_GETLK:
  389                 sg = stackgap_init(p, 0);
  390                 bfp = (struct flock *) stackgap_alloc(p, &sg, sizeof *bfp);
  391                 if ((error = copyin(arg, &lfl, sizeof lfl)))
  392                         return error;
  393                 linux_to_bsd_flock(&lfl, &bfl);
  394                 if ((error = copyout(&bfl, bfp, sizeof bfl)))
  395                         return error;
  396                 SCARG(&fca, fd) = fd;
  397                 SCARG(&fca, cmd) = F_GETLK;
  398                 SCARG(&fca, arg) = bfp;
  399                 if ((error = sys_fcntl(l, &fca, retval)))
  400                         return error;
  401                 if ((error = copyin(bfp, &bfl, sizeof bfl)))
  402                         return error;
  403                 bsd_to_linux_flock(&bfl, &lfl);
  404                 return copyout(&lfl, arg, sizeof lfl);
  405 
  406         case LINUX_F_SETLK:
  407         case LINUX_F_SETLKW:
  408                 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
  409                 if ((error = copyin(arg, &lfl, sizeof lfl)))
  410                         return error;
  411                 linux_to_bsd_flock(&lfl, &bfl);
  412                 sg = stackgap_init(p, 0);
  413                 bfp = (struct flock *) stackgap_alloc(p, &sg, sizeof *bfp);
  414                 if ((error = copyout(&bfl, bfp, sizeof bfl)))
  415                         return error;
  416                 arg = (caddr_t)bfp;
  417                 break;
  418 
  419         case LINUX_F_SETOWN:
  420         case LINUX_F_GETOWN:    
  421                 /*
  422                  * We need to route fcntl() for tty descriptors around normal
  423                  * fcntl(), since NetBSD tty TIOC{G,S}PGRP semantics is too
  424                  * restrictive for Linux F_{G,S}ETOWN. For non-tty descriptors,
  425                  * this is not a problem.
  426                  */
  427                 fdp = p->p_fd;
  428                 if ((fp = fd_getfile(fdp, fd)) == NULL)
  429                         return EBADF;
  430                 FILE_USE(fp);
  431 
  432                 /* Check it's a character device vnode */
  433                 if (fp->f_type != DTYPE_VNODE
  434                     || (vp = (struct vnode *)fp->f_data) == NULL
  435                     || vp->v_type != VCHR) {
  436                         FILE_UNUSE(fp, p);
  437 
  438             not_tty:
  439                         /* Not a tty, proceed with common fcntl() */
  440                         cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
  441                         break;
  442                 }
  443 
  444                 error = VOP_GETATTR(vp, &va, p->p_ucred, p);
  445 
  446                 FILE_UNUSE(fp, p);
  447 
  448                 if (error)
  449                         return error;
  450 
  451                 cdev = cdevsw_lookup(va.va_rdev);
  452                 if (cdev == NULL)
  453                         return (ENXIO);
  454                 d_tty = cdev->d_tty;
  455                 if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
  456                         goto not_tty;
  457 
  458                 /* set tty pg_id appropriately */
  459                 if (cmd == LINUX_F_GETOWN) {
  460                         retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
  461                         return 0;
  462                 }
  463                 if ((long)arg <= 0) {
  464                         pgid = -(long)arg;
  465                 } else {
  466                         struct proc *p1 = pfind((long)arg);
  467                         if (p1 == NULL)
  468                                 return (ESRCH);
  469                         pgid = (long)p1->p_pgrp->pg_id;
  470                 }
  471                 pgrp = pgfind(pgid);
  472                 if (pgrp == NULL || pgrp->pg_session != p->p_session)
  473                         return EPERM;
  474                 tp->t_pgrp = pgrp;
  475                 return 0;
  476 
  477         default:
  478                 return EOPNOTSUPP;
  479         }
  480 
  481         SCARG(&fca, fd) = fd;
  482         SCARG(&fca, cmd) = cmd;
  483         SCARG(&fca, arg) = arg;
  484 
  485         return sys_fcntl(l, &fca, retval);
  486 }
  487 
  488 /*
  489  * Convert a NetBSD stat structure to a Linux stat structure.
  490  * Only the order of the fields and the padding in the structure
  491  * is different. linux_fakedev is a machine-dependent function
  492  * which optionally converts device driver major/minor numbers
  493  * (XXX horrible, but what can you do against code that compares
  494  * things against constant major device numbers? sigh)
  495  */
  496 static void
  497 bsd_to_linux_stat(bsp, lsp)
  498         struct stat *bsp;
  499         struct linux_stat *lsp;
  500 {
  501 
  502         lsp->lst_dev     = linux_fakedev(bsp->st_dev, 0);
  503         lsp->lst_ino     = bsp->st_ino;
  504         lsp->lst_mode    = (linux_mode_t)bsp->st_mode;
  505         if (bsp->st_nlink >= (1 << 15))
  506                 lsp->lst_nlink = (1 << 15) - 1;
  507         else
  508                 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink;
  509         lsp->lst_uid     = bsp->st_uid;
  510         lsp->lst_gid     = bsp->st_gid;
  511         lsp->lst_rdev    = linux_fakedev(bsp->st_rdev, 1);
  512         lsp->lst_size    = bsp->st_size;
  513         lsp->lst_blksize = bsp->st_blksize;
  514         lsp->lst_blocks  = bsp->st_blocks;
  515         lsp->lst_atime   = bsp->st_atime;
  516         lsp->lst_mtime   = bsp->st_mtime;
  517         lsp->lst_ctime   = bsp->st_ctime;
  518 }
  519 
  520 /*
  521  * The stat functions below are plain sailing. stat and lstat are handled
  522  * by one function to avoid code duplication.
  523  */
  524 int
  525 linux_sys_fstat(l, v, retval)
  526         struct lwp *l;
  527         void *v;
  528         register_t *retval;
  529 {
  530         struct linux_sys_fstat_args /* {
  531                 syscallarg(int) fd;
  532                 syscallarg(linux_stat *) sp;
  533         } */ *uap = v;
  534         struct proc *p = l->l_proc;
  535         struct sys___fstat13_args fsa;
  536         struct linux_stat tmplst;
  537         struct stat *st,tmpst;
  538         caddr_t sg;
  539         int error;
  540 
  541         sg = stackgap_init(p, 0);
  542 
  543         st = stackgap_alloc(p, &sg, sizeof (struct stat));
  544 
  545         SCARG(&fsa, fd) = SCARG(uap, fd);
  546         SCARG(&fsa, sb) = st;
  547 
  548         if ((error = sys___fstat13(l, &fsa, retval)))
  549                 return error;
  550 
  551         if ((error = copyin(st, &tmpst, sizeof tmpst)))
  552                 return error;
  553 
  554         bsd_to_linux_stat(&tmpst, &tmplst);
  555 
  556         if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  557                 return error;
  558 
  559         return 0;
  560 }
  561 
  562 static int
  563 linux_stat1(l, v, retval, dolstat)
  564         struct lwp *l;
  565         void *v;
  566         register_t *retval;
  567         int dolstat;
  568 {
  569         struct sys___stat13_args sa;
  570         struct linux_stat tmplst;
  571         struct stat *st, tmpst;
  572         struct proc *p = l->l_proc;
  573         caddr_t sg;
  574         int error;
  575         struct linux_sys_stat_args *uap = v;
  576 
  577         sg = stackgap_init(p, 0);
  578         st = stackgap_alloc(p, &sg, sizeof (struct stat));
  579         if (dolstat)
  580                 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
  581         else
  582                 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  583 
  584         SCARG(&sa, ub) = st;
  585         SCARG(&sa, path) = SCARG(uap, path);
  586 
  587         if ((error = (dolstat ? sys___lstat13(l, &sa, retval) :
  588                                 sys___stat13(l, &sa, retval))))
  589                 return error;
  590 
  591         if ((error = copyin(st, &tmpst, sizeof tmpst)))
  592                 return error;
  593 
  594         bsd_to_linux_stat(&tmpst, &tmplst);
  595 
  596         if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  597                 return error;
  598 
  599         return 0;
  600 }
  601 
  602 int
  603 linux_sys_stat(l, v, retval)
  604         struct lwp *l;
  605         void *v;
  606         register_t *retval;
  607 {
  608         struct linux_sys_stat_args /* {
  609                 syscallarg(const char *) path;
  610                 syscallarg(struct linux_stat *) sp;
  611         } */ *uap = v;
  612 
  613         return linux_stat1(l, uap, retval, 0);
  614 }
  615 
  616 /* Note: this is "newlstat" in the Linux sources */
  617 /*      (we don't bother with the old lstat currently) */
  618 int
  619 linux_sys_lstat(l, v, retval)
  620         struct lwp *l;
  621         void *v;
  622         register_t *retval;
  623 {
  624         struct linux_sys_lstat_args /* {
  625                 syscallarg(const char *) path;
  626                 syscallarg(struct linux_stat *) sp;
  627         } */ *uap = v;
  628 
  629         return linux_stat1(l, uap, retval, 1);
  630 }
  631 
  632 /*
  633  * The following syscalls are mostly here because of the alternate path check.
  634  */
  635 int
  636 linux_sys_access(l, v, retval)
  637         struct lwp *l;
  638         void *v;
  639         register_t *retval;
  640 {
  641         struct linux_sys_access_args /* {
  642                 syscallarg(const char *) path;
  643                 syscallarg(int) flags;
  644         } */ *uap = v;
  645         struct proc *p = l->l_proc;
  646         caddr_t sg = stackgap_init(p, 0);
  647 
  648         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  649 
  650         return sys_access(l, uap, retval);
  651 }
  652 
  653 int
  654 linux_sys_unlink(l, v, retval)
  655         struct lwp *l;
  656         void *v;
  657         register_t *retval;
  658 
  659 {
  660         struct linux_sys_unlink_args /* {
  661                 syscallarg(const char *) path;
  662         } */ *uap = v;
  663         struct proc *p = l->l_proc;
  664         caddr_t sg = stackgap_init(p, 0);
  665         int error;
  666         struct nameidata nd;
  667 
  668         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  669 
  670         error = sys_unlink(l, uap, retval);
  671         if (error != EPERM)
  672                 return (error);
  673 
  674         /*
  675          * Linux returns EISDIR if unlink(2) is called on a directory.
  676          * We return EPERM in such cases. To emulate correct behaviour,
  677          * check if the path points to directory and return EISDIR if this
  678          * is the case.
  679          */
  680         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  681             SCARG(uap, path), p);
  682         if (namei(&nd) == 0) {
  683                 struct stat sb;
  684 
  685                 if (vn_stat(nd.ni_vp, &sb, p) == 0
  686                     && S_ISDIR(sb.st_mode))
  687                         error = EISDIR;
  688 
  689                 vput(nd.ni_vp);
  690         }
  691 
  692         return (error);
  693 }
  694 
  695 int
  696 linux_sys_chdir(l, v, retval)
  697         struct lwp *l;
  698         void *v;
  699         register_t *retval;
  700 {
  701         struct linux_sys_chdir_args /* {
  702                 syscallarg(const char *) path;
  703         } */ *uap = v;
  704         struct proc *p = l->l_proc;
  705         caddr_t sg = stackgap_init(p, 0);
  706 
  707         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  708 
  709         return sys_chdir(l, uap, retval);
  710 }
  711 
  712 int
  713 linux_sys_mknod(l, v, retval)
  714         struct lwp *l;
  715         void *v;
  716         register_t *retval;
  717 {
  718         struct linux_sys_mknod_args /* {
  719                 syscallarg(const char *) path;
  720                 syscallarg(int) mode;
  721                 syscallarg(int) dev;
  722         } */ *uap = v;
  723         struct proc *p = l->l_proc;
  724         caddr_t sg = stackgap_init(p, 0);
  725 
  726         CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  727 
  728         /*
  729          * BSD handles FIFOs separately
  730          */
  731         if (SCARG(uap, mode) & S_IFIFO) {
  732                 struct sys_mkfifo_args bma;
  733 
  734                 SCARG(&bma, path) = SCARG(uap, path);
  735                 SCARG(&bma, mode) = SCARG(uap, mode);
  736                 return sys_mkfifo(l, &bma, retval);
  737         } else {
  738                 struct sys_mknod_args bma;
  739 
  740                 SCARG(&bma, path) = SCARG(uap, path);
  741                 SCARG(&bma, mode) = SCARG(uap, mode);
  742                 /*
  743                  * Linux device numbers uses 8 bits for minor and 8 bits
  744                  * for major. Due to how we map our major and minor,
  745                  * this just fints into our dev_t. Just mask off the
  746                  * upper 16bit to remove any random junk.
  747                  */
  748                 SCARG(&bma, dev) = SCARG(uap, dev) & 0xffff;
  749                 return sys_mknod(l, &bma, retval);
  750         }
  751 }
  752 
  753 int
  754 linux_sys_chmod(l, v, retval)
  755         struct lwp *l;
  756         void *v;
  757         register_t *retval;
  758 {
  759         struct linux_sys_chmod_args /* {
  760                 syscallarg(const char *) path;
  761                 syscallarg(int) mode;
  762         } */ *uap = v;
  763         struct proc *p = l->l_proc;
  764         caddr_t sg = stackgap_init(p, 0);
  765 
  766         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  767 
  768         return sys_chmod(l, uap, retval);
  769 }
  770 
  771 #if defined(__i386__) || defined(__m68k__) || defined(__arm__)
  772 int
  773 linux_sys_chown16(l, v, retval)
  774         struct lwp *l;
  775         void *v;
  776         register_t *retval;
  777 {
  778         struct linux_sys_chown16_args /* {
  779                 syscallarg(const char *) path;
  780                 syscallarg(int) uid;
  781                 syscallarg(int) gid;
  782         } */ *uap = v;
  783         struct proc *p = l->l_proc;
  784         struct sys___posix_chown_args bca;
  785         caddr_t sg = stackgap_init(p, 0);
  786 
  787         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  788 
  789         SCARG(&bca, path) = SCARG(uap, path);
  790         SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  791                 (uid_t)-1 : SCARG(uap, uid);
  792         SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  793                 (gid_t)-1 : SCARG(uap, gid);
  794         
  795         return sys___posix_chown(l, &bca, retval);
  796 }
  797 
  798 int
  799 linux_sys_fchown16(l, v, retval)
  800         struct lwp *l;
  801         void *v;
  802         register_t *retval;
  803 {
  804         struct linux_sys_fchown16_args /* {
  805                 syscallarg(int) fd;
  806                 syscallarg(int) uid;
  807                 syscallarg(int) gid;
  808         } */ *uap = v;
  809         struct sys___posix_fchown_args bfa;
  810 
  811         SCARG(&bfa, fd) = SCARG(uap, fd);
  812         SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  813                 (uid_t)-1 : SCARG(uap, uid);
  814         SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  815                 (gid_t)-1 : SCARG(uap, gid);
  816         
  817         return sys___posix_fchown(l, &bfa, retval);
  818 }
  819 
  820 int
  821 linux_sys_lchown16(l, v, retval)
  822         struct lwp *l;
  823         void *v;
  824         register_t *retval;
  825 {
  826         struct linux_sys_lchown16_args /* {
  827                 syscallarg(char *) path;
  828                 syscallarg(int) uid;
  829                 syscallarg(int) gid;
  830         } */ *uap = v;
  831         struct proc *p = l->l_proc;
  832         struct sys___posix_lchown_args bla;
  833         caddr_t sg = stackgap_init(p, 0);
  834 
  835         CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
  836 
  837         SCARG(&bla, path) = SCARG(uap, path);
  838         SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  839                 (uid_t)-1 : SCARG(uap, uid);
  840         SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  841                 (gid_t)-1 : SCARG(uap, gid);
  842 
  843         return sys___posix_lchown(l, &bla, retval);
  844 }
  845 #endif /* __i386__ || __m68k__ || __arm__ */
  846 #if defined (__i386__) || defined (__m68k__) || \
  847     defined (__powerpc__) || defined (__mips__) || defined(__arm__)
  848 int
  849 linux_sys_chown(l, v, retval)
  850         struct lwp *l;
  851         void *v;
  852         register_t *retval;
  853 {
  854         struct linux_sys_chown_args /* {
  855                 syscallarg(char *) path;
  856                 syscallarg(int) uid;
  857                 syscallarg(int) gid;
  858         } */ *uap = v;
  859         struct proc *p = l->l_proc;
  860         caddr_t sg = stackgap_init(p, 0);
  861 
  862         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  863 
  864         return sys___posix_chown(l, uap, retval);
  865 }
  866 
  867 int
  868 linux_sys_lchown(l, v, retval)
  869         struct lwp *l;
  870         void *v;
  871         register_t *retval;
  872 {
  873         struct linux_sys_lchown_args /* {
  874                 syscallarg(char *) path;
  875                 syscallarg(int) uid;
  876                 syscallarg(int) gid;
  877         } */ *uap = v;
  878         struct proc *p = l->l_proc;
  879         caddr_t sg = stackgap_init(p, 0);
  880 
  881         CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
  882 
  883         return sys___posix_lchown(l, uap, retval);
  884 }
  885 #endif /* __i386__ || __m68k__ || __powerpc__ || __mips__ || __arm__ */
  886 
  887 int
  888 linux_sys_rename(l, v, retval)
  889         struct lwp *l;
  890         void *v;
  891         register_t *retval;
  892 {
  893         struct linux_sys_rename_args /* {
  894                 syscallarg(const char *) from;
  895                 syscallarg(const char *) to;
  896         } */ *uap = v;
  897         struct proc *p = l->l_proc;
  898         caddr_t sg = stackgap_init(p, 0);
  899 
  900         CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
  901         CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
  902 
  903         return sys___posix_rename(l, uap, retval);
  904 }
  905 
  906 int
  907 linux_sys_mkdir(l, v, retval)
  908         struct lwp *l;
  909         void *v;
  910         register_t *retval;
  911 {
  912         struct linux_sys_mkdir_args /* {
  913                 syscallarg(const char *) path;
  914                 syscallarg(int) mode;
  915         } */ *uap = v;
  916         struct proc *p = l->l_proc;
  917         caddr_t sg = stackgap_init(p, 0);
  918 
  919         CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  920 
  921         return sys_mkdir(l, uap, retval);
  922 }
  923 
  924 int
  925 linux_sys_rmdir(l, v, retval)
  926         struct lwp *l;
  927         void *v;
  928         register_t *retval;
  929 {
  930         struct linux_sys_rmdir_args /* {
  931                 syscallarg(const char *) path;
  932         } */ *uap = v;
  933         struct proc *p = l->l_proc;
  934         caddr_t sg = stackgap_init(p, 0);
  935 
  936         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  937 
  938         return sys_rmdir(l, uap, retval);
  939 }
  940 
  941 int
  942 linux_sys_symlink(l, v, retval)
  943         struct lwp *l;
  944         void *v;
  945         register_t *retval;
  946 {
  947         struct linux_sys_symlink_args /* {
  948                 syscallarg(const char *) path;
  949                 syscallarg(const char *) to;
  950         } */ *uap = v;
  951         struct proc *p = l->l_proc;
  952         caddr_t sg = stackgap_init(p, 0);
  953 
  954         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  955         CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
  956 
  957         return sys_symlink(l, uap, retval);
  958 }
  959 
  960 int
  961 linux_sys_link(l, v, retval)
  962         struct lwp *l;
  963         void *v;
  964         register_t *retval;
  965 {
  966         struct linux_sys_link_args /* {
  967                 syscallarg(const char *) path;
  968                 syscallarg(const char *) link;
  969         } */ *uap = v;
  970         struct proc *p = l->l_proc;
  971         caddr_t sg = stackgap_init(p, 0);
  972 
  973         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  974         CHECK_ALT_CREAT(p, &sg, SCARG(uap, link));
  975 
  976         return sys_link(l, uap, retval);
  977 }
  978 
  979 int
  980 linux_sys_readlink(l, v, retval)
  981         struct lwp *l;
  982         void *v;
  983         register_t *retval;
  984 {
  985         struct linux_sys_readlink_args /* {
  986                 syscallarg(const char *) name;
  987                 syscallarg(char *) buf;
  988                 syscallarg(int) count;
  989         } */ *uap = v;
  990         struct proc *p = l->l_proc;
  991         caddr_t sg = stackgap_init(p, 0);
  992 
  993         CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, name));
  994 
  995         return sys_readlink(l, uap, retval);
  996 }
  997 
  998 int
  999 linux_sys_truncate(l, v, retval)
 1000         struct lwp *l;
 1001         void *v;
 1002         register_t *retval;
 1003 {
 1004         struct linux_sys_truncate_args /* {
 1005                 syscallarg(const char *) path;
 1006                 syscallarg(long) length;
 1007         } */ *uap = v;
 1008         struct proc *p = l->l_proc;
 1009         caddr_t sg = stackgap_init(p, 0);
 1010 
 1011         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
 1012 
 1013         return compat_43_sys_truncate(l, uap, retval);
 1014 }
 1015 
 1016 /*
 1017  * This is just fsync() for now (just as it is in the Linux kernel)
 1018  * Note: this is not implemented under Linux on Alpha and Arm
 1019  *      but should still be defined in our syscalls.master.
 1020  *      (syscall #148 on the arm)
 1021  */
 1022 int
 1023 linux_sys_fdatasync(l, v, retval)
 1024         struct lwp *l;
 1025         void *v;
 1026         register_t *retval;
 1027 {
 1028 #ifdef notdef
 1029         struct linux_sys_fdatasync_args /* {
 1030                 syscallarg(int) fd;
 1031         } */ *uap = v;
 1032 #endif
 1033         return sys_fsync(l, v, retval);
 1034 }
 1035 
 1036 /*
 1037  * pread(2).
 1038  */
 1039 int
 1040 linux_sys_pread(l, v, retval)
 1041         struct lwp *l;
 1042         void *v;
 1043         register_t *retval;
 1044 {
 1045         struct linux_sys_pread_args /* {
 1046                 syscallarg(int) fd;
 1047                 syscallarg(void *) buf;
 1048                 syscallarg(size_t) nbyte;
 1049                 syscallarg(linux_off_t) offset;
 1050         } */ *uap = v;
 1051         struct sys_pread_args pra;
 1052 
 1053         SCARG(&pra, fd) = SCARG(uap, fd);
 1054         SCARG(&pra, buf) = SCARG(uap, buf);
 1055         SCARG(&pra, nbyte) = SCARG(uap, nbyte);
 1056         SCARG(&pra, offset) = SCARG(uap, offset);
 1057 
 1058         return sys_pread(l, &pra, retval);
 1059 }
 1060 
 1061 /*
 1062  * pwrite(2).
 1063  */
 1064 int
 1065 linux_sys_pwrite(l, v, retval)
 1066         struct lwp *l;
 1067         void *v;
 1068         register_t *retval;
 1069 {
 1070         struct linux_sys_pwrite_args /* {
 1071                 syscallarg(int) fd;
 1072                 syscallarg(void *) buf;
 1073                 syscallarg(size_t) nbyte;
 1074                 syscallarg(linux_off_t) offset;
 1075         } */ *uap = v;
 1076         struct sys_pwrite_args pra;
 1077 
 1078         SCARG(&pra, fd) = SCARG(uap, fd);
 1079         SCARG(&pra, buf) = SCARG(uap, buf);
 1080         SCARG(&pra, nbyte) = SCARG(uap, nbyte);
 1081         SCARG(&pra, offset) = SCARG(uap, offset);
 1082 
 1083         return sys_pwrite(l, &pra, retval);
 1084 }

Cache object: b4e50736089e9fdafe59cc62676f76f3


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