root/compat/linux/linux_file64.c

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

DEFINITIONS

This source file includes following definitions.
  1. bsd_to_linux_stat
  2. linux_sys_fstat64
  3. linux_do_stat64
  4. linux_sys_stat64
  5. linux_sys_lstat64
  6. linux_sys_truncate64
  7. linux_sys_ftruncate64
  8. bsd_to_linux_flock64
  9. linux_to_bsd_flock64
  10. linux_sys_fcntl64

    1 /*      $OpenBSD: linux_file64.c,v 1.6 2003/08/03 18:08:03 deraadt Exp $        */
    2 /*      $NetBSD: linux_file64.c,v 1.2 2000/12/12 22:24:56 jdolecek Exp $        */
    3 
    4 /*-
    5  * Copyright (c) 1995, 1998, 2000 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Frank van der Linden and Eric Haszlakiewicz.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * Linux 64bit filesystem calls. Used on 32bit archs, not used on 64bit ones.
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/namei.h>
   47 #include <sys/proc.h>
   48 #include <sys/file.h>
   49 #include <sys/stat.h>
   50 #include <sys/filedesc.h>
   51 #include <sys/ioctl.h>
   52 #include <sys/kernel.h>
   53 #include <sys/mount.h>
   54 #include <sys/malloc.h>
   55 #include <sys/vnode.h>
   56 #include <sys/tty.h>
   57 #include <sys/conf.h>
   58 
   59 #include <sys/syscallargs.h>
   60 
   61 #include <compat/linux/linux_types.h>
   62 #include <compat/linux/linux_signal.h>
   63 #include <compat/linux/linux_syscallargs.h>
   64 #include <compat/linux/linux_fcntl.h>
   65 #include <compat/linux/linux_util.h>
   66 
   67 #include <machine/linux_machdep.h>
   68 
   69 
   70 void bsd_to_linux_flock64(struct flock *, struct linux_flock64 *);
   71 void linux_to_bsd_flock64(struct linux_flock64 *, struct flock *);
   72 static void bsd_to_linux_stat(struct stat *, struct linux_stat64 *);
   73 static int linux_do_stat64(struct proc *, void *, register_t *, int);
   74 
   75 /*
   76  * Convert a OpenBSD stat structure to a Linux stat structure.
   77  * Only the order of the fields and the padding in the structure
   78  * is different. linux_fakedev is a machine-dependent function
   79  * which optionally converts device driver major/minor numbers
   80  * (XXX horrible, but what can you do against code that compares
   81  * things against constant major device numbers? sigh)
   82  */
   83 static void
   84 bsd_to_linux_stat(bsp, lsp)
   85         struct stat *bsp;
   86         struct linux_stat64 *lsp;
   87 {
   88         lsp->lst_dev     = bsp->st_dev;
   89         lsp->lst_ino     = bsp->st_ino;
   90         lsp->lst_mode    = (linux_mode_t)bsp->st_mode;
   91         if (bsp->st_nlink >= (1 << 15))
   92                 lsp->lst_nlink = (1 << 15) - 1;
   93         else
   94                 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink;
   95         lsp->lst_uid     = bsp->st_uid;
   96         lsp->lst_gid     = bsp->st_gid;
   97         lsp->lst_rdev    = linux_fakedev(bsp->st_rdev);
   98         lsp->lst_size    = bsp->st_size;
   99         lsp->lst_blksize = bsp->st_blksize;
  100         lsp->lst_blocks  = bsp->st_blocks;
  101         lsp->lst_atime   = bsp->st_atime;
  102         lsp->lst_mtime   = bsp->st_mtime;
  103         lsp->lst_ctime   = bsp->st_ctime;
  104 #if LINUX_STAT64_HAS_BROKEN_ST_INO
  105         lsp->__lst_ino   = (linux_ino_t)bsp->st_ino;
  106 #endif
  107 }
  108 
  109 /*
  110  * The stat functions below are plain sailing. stat and lstat are handled
  111  * by one function to avoid code duplication.
  112  */
  113 int
  114 linux_sys_fstat64(p, v, retval)
  115         struct proc *p;
  116         void *v;
  117         register_t *retval;
  118 {
  119         struct linux_sys_fstat64_args /* {
  120                 syscallarg(int) fd;
  121                 syscallarg(linux_stat64 *) sp;
  122         } */ *uap = v;
  123         struct sys_fstat_args fsa;
  124         struct linux_stat64 tmplst;
  125         struct stat *st,tmpst;
  126         caddr_t sg;
  127         int error;
  128 
  129         sg = stackgap_init(p->p_emul);
  130 
  131         st = stackgap_alloc(&sg, sizeof (struct stat));
  132 
  133         SCARG(&fsa, fd) = SCARG(uap, fd);
  134         SCARG(&fsa, sb) = st;
  135 
  136         if ((error = sys_fstat(p, &fsa, retval)))
  137                 return error;
  138 
  139         if ((error = copyin(st, &tmpst, sizeof tmpst)))
  140                 return error;
  141 
  142         bsd_to_linux_stat(&tmpst, &tmplst);
  143 
  144         if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  145                 return error;
  146 
  147         return 0;
  148 }
  149 
  150 static int
  151 linux_do_stat64(p, v, retval, dolstat)
  152         struct proc *p;
  153         void *v;
  154         register_t *retval;
  155         int dolstat;
  156 {
  157         struct sys_stat_args sa;
  158         struct linux_stat64 tmplst;
  159         struct stat *st, tmpst;
  160         caddr_t sg;
  161         int error;
  162         struct linux_sys_stat64_args *uap = v;
  163 
  164         sg = stackgap_init(p->p_emul);
  165         st = stackgap_alloc(&sg, sizeof (struct stat));
  166         LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  167 
  168         SCARG(&sa, ub) = st;
  169         SCARG(&sa, path) = SCARG(uap, path);
  170 
  171         if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
  172                                 sys_stat(p, &sa, retval))))
  173                 return error;
  174 
  175         if ((error = copyin(st, &tmpst, sizeof tmpst)))
  176                 return error;
  177 
  178         bsd_to_linux_stat(&tmpst, &tmplst);
  179 
  180         if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
  181                 return error;
  182 
  183         return 0;
  184 }
  185 
  186 int
  187 linux_sys_stat64(p, v, retval)
  188         struct proc *p;
  189         void *v;
  190         register_t *retval;
  191 {
  192         struct linux_sys_stat64_args /* {
  193                 syscallarg(const char *) path;
  194                 syscallarg(struct linux_stat64 *) sp;
  195         } */ *uap = v;
  196 
  197         return linux_do_stat64(p, uap, retval, 0);
  198 }
  199 
  200 int
  201 linux_sys_lstat64(p, v, retval)
  202         struct proc *p;
  203         void *v;
  204         register_t *retval;
  205 {
  206         struct linux_sys_lstat64_args /* {
  207                 syscallarg(char *) path;
  208                 syscallarg(struct linux_stat64 *) sp;
  209         } */ *uap = v;
  210 
  211         return linux_do_stat64(p, uap, retval, 1);
  212 }
  213 
  214 int
  215 linux_sys_truncate64(p, v, retval)
  216         struct proc *p;
  217         void *v;
  218         register_t *retval;
  219 {
  220         struct linux_sys_truncate64_args /* {
  221                 syscallarg(char *) path;
  222                 syscallarg(off_t) length;
  223         } */ *uap = v;
  224         struct sys_truncate_args ta;
  225         caddr_t sg = stackgap_init(p->p_emul);
  226 
  227         LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
  228 
  229         SCARG(&ta, path) = SCARG(uap, path);
  230         SCARG(&ta, length) = SCARG(uap, length);
  231 
  232         return sys_truncate(p, &ta, retval);
  233 }
  234 
  235 /*
  236  * This is needed due to padding in OpenBSD's sys_ftruncate_args
  237  */
  238 int
  239 linux_sys_ftruncate64(p, v, retval)
  240         struct proc *p;
  241         void *v;
  242         register_t *retval;
  243 {
  244         struct linux_sys_ftruncate64_args /* {
  245                 syscallarg(int) fd;
  246                 syscallarg(off_t) length;
  247         } */ *uap = v;
  248         struct sys_ftruncate_args fta;
  249 
  250         SCARG(&fta, fd) = SCARG(uap, fd);
  251         SCARG(&fta, length) = SCARG(uap, length);
  252 
  253         return sys_ftruncate(p, &fta, retval);
  254 }
  255 
  256 /*
  257  * The next two functions take care of converting the flock
  258  * structure back and forth between Linux and OpenBSD format.
  259  * The only difference in the structures is the order of
  260  * the fields, and the 'whence' value.
  261  */
  262 void
  263 bsd_to_linux_flock64(struct flock *bfp, struct linux_flock64 *lfp)
  264 {
  265         lfp->l_start = bfp->l_start;
  266         lfp->l_len = bfp->l_len;
  267         lfp->l_pid = bfp->l_pid;
  268         lfp->l_whence = bfp->l_whence;
  269         switch (bfp->l_type) {
  270         case F_RDLCK:
  271                 lfp->l_type = LINUX_F_RDLCK;
  272                 break;
  273         case F_UNLCK:
  274                 lfp->l_type = LINUX_F_UNLCK;
  275                 break;
  276         case F_WRLCK:
  277                 lfp->l_type = LINUX_F_WRLCK;
  278                 break;
  279         }
  280 }
  281 
  282 void
  283 linux_to_bsd_flock64(struct linux_flock64 *lfp, struct flock *bfp)
  284 {
  285         bfp->l_start = lfp->l_start;
  286         bfp->l_len = lfp->l_len;
  287         bfp->l_pid = lfp->l_pid;
  288         bfp->l_whence = lfp->l_whence;
  289         switch (lfp->l_type) {
  290         case LINUX_F_RDLCK:
  291                 bfp->l_type = F_RDLCK;
  292                 break;
  293         case LINUX_F_UNLCK:
  294                 bfp->l_type = F_UNLCK;
  295                 break;
  296         case LINUX_F_WRLCK:
  297                 bfp->l_type = F_WRLCK;
  298                 break;
  299         }
  300 }
  301 
  302 int
  303 linux_sys_fcntl64(p, v, retval)
  304         struct proc *p;
  305         void *v;
  306         register_t *retval;
  307 {
  308         struct linux_sys_fcntl64_args /* {
  309                 syscallarg(u_int) fd;
  310                 syscallarg(u_int) cmd;
  311                 syscallarg(void *) arg;
  312         } */ *uap = v;
  313         int fd, cmd, error;
  314         caddr_t arg, sg;
  315         struct linux_flock64 lfl;
  316         struct flock *bfp, bfl;
  317         struct sys_fcntl_args fca;
  318 
  319         fd = SCARG(uap, fd);
  320         cmd = SCARG(uap, cmd);
  321         arg = (caddr_t) SCARG(uap, arg);
  322 
  323         switch (cmd) {
  324         case LINUX_F_GETLK64:
  325                 sg = stackgap_init(p->p_emul);
  326                 if ((error = copyin(arg, &lfl, sizeof lfl)))
  327                         return error;
  328                 linux_to_bsd_flock64(&lfl, &bfl);
  329                 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
  330                 SCARG(&fca, fd) = fd;
  331                 SCARG(&fca, cmd) = F_GETLK;
  332                 SCARG(&fca, arg) = bfp;
  333                 if ((error = copyout(&bfl, bfp, sizeof bfl)))
  334                         return error;
  335                 if ((error = sys_fcntl(p, &fca, retval)))
  336                         return error;
  337                 if ((error = copyin(bfp, &bfl, sizeof bfl)))
  338                         return error;
  339                 bsd_to_linux_flock64(&bfl, &lfl);
  340                 error = copyout(&lfl, arg, sizeof lfl);
  341                 return (error);
  342         case LINUX_F_SETLK64:
  343         case LINUX_F_SETLKW64:
  344                 cmd = (cmd == LINUX_F_SETLK64 ? F_SETLK : F_SETLKW);
  345                 if ((error = copyin(arg, &lfl, sizeof lfl)))
  346                         return error;
  347                 linux_to_bsd_flock64(&lfl, &bfl);
  348                 sg = stackgap_init(p->p_emul);
  349                 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
  350                 if ((error = copyout(&bfl, bfp, sizeof bfl)))
  351                         return error;
  352                 SCARG(&fca, fd) = fd;
  353                 SCARG(&fca, cmd) = cmd;
  354                 SCARG(&fca, arg) = bfp;
  355                 return (sys_fcntl(p, &fca, retval));
  356         default:
  357                 return (linux_sys_fcntl(p, v, retval));
  358         }
  359         /* NOTREACHED */
  360 }

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