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.66 2005/03/10 14:12:28 christos 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.66 2005/03/10 14:12:28 christos 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 slightly 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 #ifdef LINUX_STAT_HAS_NSEC
  519         lsp->lst_atime_nsec   = bsp->st_atimensec;
  520         lsp->lst_mtime_nsec   = bsp->st_mtimensec;
  521         lsp->lst_ctime_nsec   = bsp->st_ctimensec;
  522 #endif
  523 }
  524 
  525 /*
  526  * The stat functions below are plain sailing. stat and lstat are handled
  527  * by one function to avoid code duplication.
  528  */
  529 int
  530 linux_sys_fstat(l, v, retval)
  531         struct lwp *l;
  532         void *v;
  533         register_t *retval;
  534 {
  535         struct linux_sys_fstat_args /* {
  536                 syscallarg(int) fd;
  537                 syscallarg(linux_stat *) sp;
  538         } */ *uap = v;
  539         struct proc *p = l->l_proc;
  540         struct sys___fstat13_args fsa;
  541         struct linux_stat tmplst;
  542         struct stat *st,tmpst;
  543         caddr_t sg;
  544         int error;
  545 
  546         sg = stackgap_init(p, 0);
  547 
  548         st = stackgap_alloc(p, &sg, sizeof (struct stat));
  549 
  550         SCARG(&fsa, fd) = SCARG(uap, fd);
  551         SCARG(&fsa, sb) = st;
  552 
  553         if ((error = sys___fstat13(l, &fsa, retval)))
  554                 return error;
  555 
  556         if ((error = copyin(st, &tmpst, sizeof tmpst)))
  557                 return error;
  558 
  559         bsd_to_linux_stat(&tmpst, &tmplst);
  560 
  561         if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  562                 return error;
  563 
  564         return 0;
  565 }
  566 
  567 static int
  568 linux_stat1(l, v, retval, dolstat)
  569         struct lwp *l;
  570         void *v;
  571         register_t *retval;
  572         int dolstat;
  573 {
  574         struct sys___stat13_args sa;
  575         struct linux_stat tmplst;
  576         struct stat *st, tmpst;
  577         struct proc *p = l->l_proc;
  578         caddr_t sg;
  579         int error;
  580         struct linux_sys_stat_args *uap = v;
  581 
  582         sg = stackgap_init(p, 0);
  583         st = stackgap_alloc(p, &sg, sizeof (struct stat));
  584         if (dolstat)
  585                 CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
  586         else
  587                 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  588 
  589         SCARG(&sa, ub) = st;
  590         SCARG(&sa, path) = SCARG(uap, path);
  591 
  592         if ((error = (dolstat ? sys___lstat13(l, &sa, retval) :
  593                                 sys___stat13(l, &sa, retval))))
  594                 return error;
  595 
  596         if ((error = copyin(st, &tmpst, sizeof tmpst)))
  597                 return error;
  598 
  599         bsd_to_linux_stat(&tmpst, &tmplst);
  600 
  601         if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  602                 return error;
  603 
  604         return 0;
  605 }
  606 
  607 int
  608 linux_sys_stat(l, v, retval)
  609         struct lwp *l;
  610         void *v;
  611         register_t *retval;
  612 {
  613         struct linux_sys_stat_args /* {
  614                 syscallarg(const char *) path;
  615                 syscallarg(struct linux_stat *) sp;
  616         } */ *uap = v;
  617 
  618         return linux_stat1(l, uap, retval, 0);
  619 }
  620 
  621 /* Note: this is "newlstat" in the Linux sources */
  622 /*      (we don't bother with the old lstat currently) */
  623 int
  624 linux_sys_lstat(l, v, retval)
  625         struct lwp *l;
  626         void *v;
  627         register_t *retval;
  628 {
  629         struct linux_sys_lstat_args /* {
  630                 syscallarg(const char *) path;
  631                 syscallarg(struct linux_stat *) sp;
  632         } */ *uap = v;
  633 
  634         return linux_stat1(l, uap, retval, 1);
  635 }
  636 
  637 /*
  638  * The following syscalls are mostly here because of the alternate path check.
  639  */
  640 int
  641 linux_sys_access(l, v, retval)
  642         struct lwp *l;
  643         void *v;
  644         register_t *retval;
  645 {
  646         struct linux_sys_access_args /* {
  647                 syscallarg(const char *) path;
  648                 syscallarg(int) flags;
  649         } */ *uap = v;
  650         struct proc *p = l->l_proc;
  651         caddr_t sg = stackgap_init(p, 0);
  652 
  653         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  654 
  655         return sys_access(l, uap, retval);
  656 }
  657 
  658 int
  659 linux_sys_unlink(l, v, retval)
  660         struct lwp *l;
  661         void *v;
  662         register_t *retval;
  663 
  664 {
  665         struct linux_sys_unlink_args /* {
  666                 syscallarg(const char *) path;
  667         } */ *uap = v;
  668         struct proc *p = l->l_proc;
  669         caddr_t sg = stackgap_init(p, 0);
  670         int error;
  671         struct nameidata nd;
  672 
  673         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  674 
  675         error = sys_unlink(l, uap, retval);
  676         if (error != EPERM)
  677                 return (error);
  678 
  679         /*
  680          * Linux returns EISDIR if unlink(2) is called on a directory.
  681          * We return EPERM in such cases. To emulate correct behaviour,
  682          * check if the path points to directory and return EISDIR if this
  683          * is the case.
  684          */
  685         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
  686             SCARG(uap, path), p);
  687         if (namei(&nd) == 0) {
  688                 struct stat sb;
  689 
  690                 if (vn_stat(nd.ni_vp, &sb, p) == 0
  691                     && S_ISDIR(sb.st_mode))
  692                         error = EISDIR;
  693 
  694                 vput(nd.ni_vp);
  695         }
  696 
  697         return (error);
  698 }
  699 
  700 int
  701 linux_sys_chdir(l, v, retval)
  702         struct lwp *l;
  703         void *v;
  704         register_t *retval;
  705 {
  706         struct linux_sys_chdir_args /* {
  707                 syscallarg(const char *) path;
  708         } */ *uap = v;
  709         struct proc *p = l->l_proc;
  710         caddr_t sg = stackgap_init(p, 0);
  711 
  712         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  713 
  714         return sys_chdir(l, uap, retval);
  715 }
  716 
  717 int
  718 linux_sys_mknod(l, v, retval)
  719         struct lwp *l;
  720         void *v;
  721         register_t *retval;
  722 {
  723         struct linux_sys_mknod_args /* {
  724                 syscallarg(const char *) path;
  725                 syscallarg(int) mode;
  726                 syscallarg(int) dev;
  727         } */ *uap = v;
  728         struct proc *p = l->l_proc;
  729         caddr_t sg = stackgap_init(p, 0);
  730 
  731         CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  732 
  733         /*
  734          * BSD handles FIFOs separately
  735          */
  736         if (SCARG(uap, mode) & S_IFIFO) {
  737                 struct sys_mkfifo_args bma;
  738 
  739                 SCARG(&bma, path) = SCARG(uap, path);
  740                 SCARG(&bma, mode) = SCARG(uap, mode);
  741                 return sys_mkfifo(l, &bma, retval);
  742         } else {
  743                 struct sys_mknod_args bma;
  744 
  745                 SCARG(&bma, path) = SCARG(uap, path);
  746                 SCARG(&bma, mode) = SCARG(uap, mode);
  747                 /*
  748                  * Linux device numbers uses 8 bits for minor and 8 bits
  749                  * for major. Due to how we map our major and minor,
  750                  * this just fints into our dev_t. Just mask off the
  751                  * upper 16bit to remove any random junk.
  752                  */
  753                 SCARG(&bma, dev) = SCARG(uap, dev) & 0xffff;
  754                 return sys_mknod(l, &bma, retval);
  755         }
  756 }
  757 
  758 int
  759 linux_sys_chmod(l, v, retval)
  760         struct lwp *l;
  761         void *v;
  762         register_t *retval;
  763 {
  764         struct linux_sys_chmod_args /* {
  765                 syscallarg(const char *) path;
  766                 syscallarg(int) mode;
  767         } */ *uap = v;
  768         struct proc *p = l->l_proc;
  769         caddr_t sg = stackgap_init(p, 0);
  770 
  771         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  772 
  773         return sys_chmod(l, uap, retval);
  774 }
  775 
  776 #if defined(__i386__) || defined(__m68k__) || defined(__arm__)
  777 int
  778 linux_sys_chown16(l, v, retval)
  779         struct lwp *l;
  780         void *v;
  781         register_t *retval;
  782 {
  783         struct linux_sys_chown16_args /* {
  784                 syscallarg(const char *) path;
  785                 syscallarg(int) uid;
  786                 syscallarg(int) gid;
  787         } */ *uap = v;
  788         struct proc *p = l->l_proc;
  789         struct sys___posix_chown_args bca;
  790         caddr_t sg = stackgap_init(p, 0);
  791 
  792         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  793 
  794         SCARG(&bca, path) = SCARG(uap, path);
  795         SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  796                 (uid_t)-1 : SCARG(uap, uid);
  797         SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  798                 (gid_t)-1 : SCARG(uap, gid);
  799 
  800         return sys___posix_chown(l, &bca, retval);
  801 }
  802 
  803 int
  804 linux_sys_fchown16(l, v, retval)
  805         struct lwp *l;
  806         void *v;
  807         register_t *retval;
  808 {
  809         struct linux_sys_fchown16_args /* {
  810                 syscallarg(int) fd;
  811                 syscallarg(int) uid;
  812                 syscallarg(int) gid;
  813         } */ *uap = v;
  814         struct sys___posix_fchown_args bfa;
  815 
  816         SCARG(&bfa, fd) = SCARG(uap, fd);
  817         SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  818                 (uid_t)-1 : SCARG(uap, uid);
  819         SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  820                 (gid_t)-1 : SCARG(uap, gid);
  821 
  822         return sys___posix_fchown(l, &bfa, retval);
  823 }
  824 
  825 int
  826 linux_sys_lchown16(l, v, retval)
  827         struct lwp *l;
  828         void *v;
  829         register_t *retval;
  830 {
  831         struct linux_sys_lchown16_args /* {
  832                 syscallarg(char *) path;
  833                 syscallarg(int) uid;
  834                 syscallarg(int) gid;
  835         } */ *uap = v;
  836         struct proc *p = l->l_proc;
  837         struct sys___posix_lchown_args bla;
  838         caddr_t sg = stackgap_init(p, 0);
  839 
  840         CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
  841 
  842         SCARG(&bla, path) = SCARG(uap, path);
  843         SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
  844                 (uid_t)-1 : SCARG(uap, uid);
  845         SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
  846                 (gid_t)-1 : SCARG(uap, gid);
  847 
  848         return sys___posix_lchown(l, &bla, retval);
  849 }
  850 #endif /* __i386__ || __m68k__ || __arm__ */
  851 #if defined (__i386__) || defined (__m68k__) || \
  852     defined (__powerpc__) || defined (__mips__) || defined(__arm__)
  853 int
  854 linux_sys_chown(l, v, retval)
  855         struct lwp *l;
  856         void *v;
  857         register_t *retval;
  858 {
  859         struct linux_sys_chown_args /* {
  860                 syscallarg(char *) path;
  861                 syscallarg(int) uid;
  862                 syscallarg(int) gid;
  863         } */ *uap = v;
  864         struct proc *p = l->l_proc;
  865         caddr_t sg = stackgap_init(p, 0);
  866 
  867         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  868 
  869         return sys___posix_chown(l, uap, retval);
  870 }
  871 
  872 int
  873 linux_sys_lchown(l, v, retval)
  874         struct lwp *l;
  875         void *v;
  876         register_t *retval;
  877 {
  878         struct linux_sys_lchown_args /* {
  879                 syscallarg(char *) path;
  880                 syscallarg(int) uid;
  881                 syscallarg(int) gid;
  882         } */ *uap = v;
  883         struct proc *p = l->l_proc;
  884         caddr_t sg = stackgap_init(p, 0);
  885 
  886         CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, path));
  887 
  888         return sys___posix_lchown(l, uap, retval);
  889 }
  890 #endif /* __i386__ || __m68k__ || __powerpc__ || __mips__ || __arm__ */
  891 
  892 int
  893 linux_sys_rename(l, v, retval)
  894         struct lwp *l;
  895         void *v;
  896         register_t *retval;
  897 {
  898         struct linux_sys_rename_args /* {
  899                 syscallarg(const char *) from;
  900                 syscallarg(const char *) to;
  901         } */ *uap = v;
  902         struct proc *p = l->l_proc;
  903         caddr_t sg = stackgap_init(p, 0);
  904 
  905         CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
  906         CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
  907 
  908         return sys___posix_rename(l, uap, retval);
  909 }
  910 
  911 int
  912 linux_sys_mkdir(l, v, retval)
  913         struct lwp *l;
  914         void *v;
  915         register_t *retval;
  916 {
  917         struct linux_sys_mkdir_args /* {
  918                 syscallarg(const char *) path;
  919                 syscallarg(int) mode;
  920         } */ *uap = v;
  921         struct proc *p = l->l_proc;
  922         caddr_t sg = stackgap_init(p, 0);
  923 
  924         CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
  925 
  926         return sys_mkdir(l, uap, retval);
  927 }
  928 
  929 int
  930 linux_sys_rmdir(l, v, retval)
  931         struct lwp *l;
  932         void *v;
  933         register_t *retval;
  934 {
  935         struct linux_sys_rmdir_args /* {
  936                 syscallarg(const char *) path;
  937         } */ *uap = v;
  938         struct proc *p = l->l_proc;
  939         caddr_t sg = stackgap_init(p, 0);
  940 
  941         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  942 
  943         return sys_rmdir(l, uap, retval);
  944 }
  945 
  946 int
  947 linux_sys_symlink(l, v, retval)
  948         struct lwp *l;
  949         void *v;
  950         register_t *retval;
  951 {
  952         struct linux_sys_symlink_args /* {
  953                 syscallarg(const char *) path;
  954                 syscallarg(const char *) to;
  955         } */ *uap = v;
  956         struct proc *p = l->l_proc;
  957         caddr_t sg = stackgap_init(p, 0);
  958 
  959         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  960         CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
  961 
  962         return sys_symlink(l, uap, retval);
  963 }
  964 
  965 int
  966 linux_sys_link(l, v, retval)
  967         struct lwp *l;
  968         void *v;
  969         register_t *retval;
  970 {
  971         struct linux_sys_link_args /* {
  972                 syscallarg(const char *) path;
  973                 syscallarg(const char *) link;
  974         } */ *uap = v;
  975         struct proc *p = l->l_proc;
  976         caddr_t sg = stackgap_init(p, 0);
  977 
  978         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  979         CHECK_ALT_CREAT(p, &sg, SCARG(uap, link));
  980 
  981         return sys_link(l, uap, retval);
  982 }
  983 
  984 int
  985 linux_sys_readlink(l, v, retval)
  986         struct lwp *l;
  987         void *v;
  988         register_t *retval;
  989 {
  990         struct linux_sys_readlink_args /* {
  991                 syscallarg(const char *) name;
  992                 syscallarg(char *) buf;
  993                 syscallarg(int) count;
  994         } */ *uap = v;
  995         struct proc *p = l->l_proc;
  996         caddr_t sg = stackgap_init(p, 0);
  997 
  998         CHECK_ALT_SYMLINK(p, &sg, SCARG(uap, name));
  999 
 1000         return sys_readlink(l, uap, retval);
 1001 }
 1002 
 1003 int
 1004 linux_sys_truncate(l, v, retval)
 1005         struct lwp *l;
 1006         void *v;
 1007         register_t *retval;
 1008 {
 1009         struct linux_sys_truncate_args /* {
 1010                 syscallarg(const char *) path;
 1011                 syscallarg(long) length;
 1012         } */ *uap = v;
 1013         struct proc *p = l->l_proc;
 1014         caddr_t sg = stackgap_init(p, 0);
 1015 
 1016         CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
 1017 
 1018         return compat_43_sys_truncate(l, uap, retval);
 1019 }
 1020 
 1021 /*
 1022  * This is just fsync() for now (just as it is in the Linux kernel)
 1023  * Note: this is not implemented under Linux on Alpha and Arm
 1024  *      but should still be defined in our syscalls.master.
 1025  *      (syscall #148 on the arm)
 1026  */
 1027 int
 1028 linux_sys_fdatasync(l, v, retval)
 1029         struct lwp *l;
 1030         void *v;
 1031         register_t *retval;
 1032 {
 1033 #ifdef notdef
 1034         struct linux_sys_fdatasync_args /* {
 1035                 syscallarg(int) fd;
 1036         } */ *uap = v;
 1037 #endif
 1038         return sys_fsync(l, v, retval);
 1039 }
 1040 
 1041 /*
 1042  * pread(2).
 1043  */
 1044 int
 1045 linux_sys_pread(l, v, retval)
 1046         struct lwp *l;
 1047         void *v;
 1048         register_t *retval;
 1049 {
 1050         struct linux_sys_pread_args /* {
 1051                 syscallarg(int) fd;
 1052                 syscallarg(void *) buf;
 1053                 syscallarg(size_t) nbyte;
 1054                 syscallarg(linux_off_t) offset;
 1055         } */ *uap = v;
 1056         struct sys_pread_args pra;
 1057 
 1058         SCARG(&pra, fd) = SCARG(uap, fd);
 1059         SCARG(&pra, buf) = SCARG(uap, buf);
 1060         SCARG(&pra, nbyte) = SCARG(uap, nbyte);
 1061         SCARG(&pra, offset) = SCARG(uap, offset);
 1062 
 1063         return sys_pread(l, &pra, retval);
 1064 }
 1065 
 1066 /*
 1067  * pwrite(2).
 1068  */
 1069 int
 1070 linux_sys_pwrite(l, v, retval)
 1071         struct lwp *l;
 1072         void *v;
 1073         register_t *retval;
 1074 {
 1075         struct linux_sys_pwrite_args /* {
 1076                 syscallarg(int) fd;
 1077                 syscallarg(void *) buf;
 1078                 syscallarg(size_t) nbyte;
 1079                 syscallarg(linux_off_t) offset;
 1080         } */ *uap = v;
 1081         struct sys_pwrite_args pra;
 1082 
 1083         SCARG(&pra, fd) = SCARG(uap, fd);
 1084         SCARG(&pra, buf) = SCARG(uap, buf);
 1085         SCARG(&pra, nbyte) = SCARG(uap, nbyte);
 1086         SCARG(&pra, offset) = SCARG(uap, offset);
 1087 
 1088         return sys_pwrite(l, &pra, retval);
 1089 }

Cache object: b78e401153577ec2f8280b52c02aec2d


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