1 /* $NetBSD: linux_file64.c,v 1.5 2001/10/14 17:15:58 manu Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998, 2000 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 * Linux 64bit filesystem calls. Used on 32bit archs, not used on 64bit ones. 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/namei.h> 46 #include <sys/proc.h> 47 #include <sys/file.h> 48 #include <sys/stat.h> 49 #include <sys/filedesc.h> 50 #include <sys/ioctl.h> 51 #include <sys/kernel.h> 52 #include <sys/mount.h> 53 #include <sys/malloc.h> 54 #include <sys/vnode.h> 55 #include <sys/tty.h> 56 #include <sys/conf.h> 57 58 #include <sys/syscallargs.h> 59 60 #include <compat/linux/common/linux_types.h> 61 #include <compat/linux/common/linux_signal.h> 62 #include <compat/linux/common/linux_fcntl.h> 63 #include <compat/linux/common/linux_util.h> 64 #include <compat/linux/common/linux_machdep.h> 65 66 #include <compat/linux/linux_syscallargs.h> 67 68 static void bsd_to_linux_stat __P((struct stat *, struct linux_stat64 *)); 69 static int linux_do_stat64 __P((struct proc *, void *, register_t *, int)); 70 71 /* 72 * Convert a NetBSD stat structure to a Linux stat structure. 73 * Only the order of the fields and the padding in the structure 74 * is different. linux_fakedev is a machine-dependent function 75 * which optionally converts device driver major/minor numbers 76 * (XXX horrible, but what can you do against code that compares 77 * things against constant major device numbers? sigh) 78 */ 79 static void 80 bsd_to_linux_stat(bsp, lsp) 81 struct stat *bsp; 82 struct linux_stat64 *lsp; 83 { 84 lsp->lst_dev = bsp->st_dev; 85 lsp->lst_ino = bsp->st_ino; 86 lsp->lst_mode = (linux_mode_t)bsp->st_mode; 87 if (bsp->st_nlink >= (1 << 15)) 88 lsp->lst_nlink = (1 << 15) - 1; 89 else 90 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink; 91 lsp->lst_uid = bsp->st_uid; 92 lsp->lst_gid = bsp->st_gid; 93 lsp->lst_rdev = linux_fakedev(bsp->st_rdev); 94 lsp->lst_size = bsp->st_size; 95 lsp->lst_blksize = bsp->st_blksize; 96 lsp->lst_blocks = bsp->st_blocks; 97 lsp->lst_atime = bsp->st_atime; 98 lsp->lst_mtime = bsp->st_mtime; 99 lsp->lst_ctime = bsp->st_ctime; 100 } 101 102 /* 103 * The stat functions below are plain sailing. stat and lstat are handled 104 * by one function to avoid code duplication. 105 */ 106 int 107 linux_sys_fstat64(p, v, retval) 108 struct proc *p; 109 void *v; 110 register_t *retval; 111 { 112 struct linux_sys_fstat64_args /* { 113 syscallarg(int) fd; 114 syscallarg(struct linux_stat64 *) sp; 115 } */ *uap = v; 116 struct sys___fstat13_args fsa; 117 struct linux_stat64 tmplst; 118 struct stat *st,tmpst; 119 caddr_t sg; 120 int error; 121 122 sg = stackgap_init(p->p_emul); 123 124 st = stackgap_alloc(&sg, sizeof (struct stat)); 125 126 SCARG(&fsa, fd) = SCARG(uap, fd); 127 SCARG(&fsa, sb) = st; 128 129 if ((error = sys___fstat13(p, &fsa, retval))) 130 return error; 131 132 if ((error = copyin(st, &tmpst, sizeof tmpst))) 133 return error; 134 135 bsd_to_linux_stat(&tmpst, &tmplst); 136 137 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 138 return error; 139 140 return 0; 141 } 142 143 static int 144 linux_do_stat64(p, v, retval, dolstat) 145 struct proc *p; 146 void *v; 147 register_t *retval; 148 int dolstat; 149 { 150 struct sys___stat13_args sa; 151 struct linux_stat64 tmplst; 152 struct stat *st, tmpst; 153 caddr_t sg; 154 int error; 155 struct linux_sys_stat64_args *uap = v; 156 157 sg = stackgap_init(p->p_emul); 158 st = stackgap_alloc(&sg, sizeof (struct stat)); 159 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 160 161 SCARG(&sa, ub) = st; 162 SCARG(&sa, path) = SCARG(uap, path); 163 164 if ((error = (dolstat ? sys___lstat13(p, &sa, retval) : 165 sys___stat13(p, &sa, retval)))) 166 return error; 167 168 if ((error = copyin(st, &tmpst, sizeof tmpst))) 169 return error; 170 171 bsd_to_linux_stat(&tmpst, &tmplst); 172 173 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 174 return error; 175 176 return 0; 177 } 178 179 int 180 linux_sys_stat64(p, v, retval) 181 struct proc *p; 182 void *v; 183 register_t *retval; 184 { 185 struct linux_sys_stat64_args /* { 186 syscallarg(const char *) path; 187 syscallarg(struct linux_stat64 *) sp; 188 } */ *uap = v; 189 190 return linux_do_stat64(p, uap, retval, 0); 191 } 192 193 int 194 linux_sys_lstat64(p, v, retval) 195 struct proc *p; 196 void *v; 197 register_t *retval; 198 { 199 struct linux_sys_lstat64_args /* { 200 syscallarg(const char *) path; 201 syscallarg(struct linux_stat64 *) sp; 202 } */ *uap = v; 203 204 return linux_do_stat64(p, uap, retval, 1); 205 } 206 207 int 208 linux_sys_truncate64(p, v, retval) 209 struct proc *p; 210 void *v; 211 register_t *retval; 212 { 213 struct linux_sys_truncate64_args /* { 214 syscallarg(const char *) path; 215 syscallarg(off_t) length; 216 } */ *uap = v; 217 caddr_t sg = stackgap_init(p->p_emul); 218 219 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 220 221 return sys_truncate(p, uap, retval); 222 } 223 224 #ifdef __mips__ /* i386 and powerpc could use it too */ 225 int 226 linux_sys_fcntl64(p, v, retval) 227 struct proc *p; 228 void *v; 229 register_t *retval; 230 { 231 struct linux_sys_fcntl64_args /* { 232 syscallarg(unsigned int) fd; 233 syscallarg(unsigned int) cmd; 234 syscallarg(unsigned long) arg; 235 } */ *uap = v; 236 unsigned int fd, cmd; 237 unsigned long arg; 238 int error; 239 240 fd = SCARG(uap, fd); 241 cmd = SCARG(uap, cmd); 242 arg = SCARG(uap, arg); 243 244 switch (cmd) { 245 /* XXX implement this later */ 246 case LINUX_F_GETLK64: 247 error = 0; 248 break; 249 case LINUX_F_SETLK64: 250 error = 0; 251 break; 252 case LINUX_F_SETLKW64: 253 error = 0; 254 break; 255 default: 256 error = linux_sys_fcntl(p, v, retval); 257 break; 258 } 259 260 return error; 261 } 262 #endif /* __mips__ */ 263