1 /* $NetBSD: linux_misc_notalpha.c,v 1.49 1998/10/04 00:02:37 fvdl 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 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/mman.h> 43 #include <sys/mount.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/namei.h> 47 #include <sys/ptrace.h> 48 #include <sys/resource.h> 49 #include <sys/resourcevar.h> 50 #include <sys/wait.h> 51 52 #include <sys/syscallargs.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_param.h> 56 57 #include <compat/linux/common/linux_types.h> 58 #include <compat/linux/common/linux_fcntl.h> 59 #include <compat/linux/common/linux_misc.h> 60 #include <compat/linux/common/linux_mmap.h> 61 #include <compat/linux/common/linux_signal.h> 62 #include <compat/linux/common/linux_util.h> 63 64 #include <compat/linux/linux_syscallargs.h> 65 66 /* 67 * This file contains routines which are used 68 * on every linux architechture except the Alpha. 69 */ 70 71 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */ 72 /* Not used on: alpha */ 73 74 /* 75 * Alarm. This is a libc call which uses setitimer(2) in NetBSD. 76 * Fiddle with the timers to make it work. 77 */ 78 int 79 linux_sys_alarm(p, v, retval) 80 struct proc *p; 81 void *v; 82 register_t *retval; 83 { 84 struct linux_sys_alarm_args /* { 85 syscallarg(unsigned int) secs; 86 } */ *uap = v; 87 int s; 88 struct itimerval *itp, it; 89 90 itp = &p->p_realtimer; 91 s = splclock(); 92 /* 93 * Clear any pending timer alarms. 94 */ 95 untimeout(realitexpire, p); 96 timerclear(&itp->it_interval); 97 if (timerisset(&itp->it_value) && 98 timercmp(&itp->it_value, &time, >)) 99 timersub(&itp->it_value, &time, &itp->it_value); 100 /* 101 * Return how many seconds were left (rounded up) 102 */ 103 retval[0] = itp->it_value.tv_sec; 104 if (itp->it_value.tv_usec) 105 retval[0]++; 106 107 /* 108 * alarm(0) just resets the timer. 109 */ 110 if (SCARG(uap, secs) == 0) { 111 timerclear(&itp->it_value); 112 splx(s); 113 return 0; 114 } 115 116 /* 117 * Check the new alarm time for sanity, and set it. 118 */ 119 timerclear(&it.it_interval); 120 it.it_value.tv_sec = SCARG(uap, secs); 121 it.it_value.tv_usec = 0; 122 if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) { 123 splx(s); 124 return (EINVAL); 125 } 126 127 if (timerisset(&it.it_value)) { 128 timeradd(&it.it_value, &time, &it.it_value); 129 timeout(realitexpire, p, hzto(&it.it_value)); 130 } 131 p->p_realtimer = it; 132 splx(s); 133 134 return 0; 135 } 136 137 int 138 linux_sys_nice(p, v, retval) 139 struct proc *p; 140 void *v; 141 register_t *retval; 142 { 143 struct linux_sys_nice_args /* { 144 syscallarg(int) incr; 145 } */ *uap = v; 146 struct sys_setpriority_args bsa; 147 148 SCARG(&bsa, which) = PRIO_PROCESS; 149 SCARG(&bsa, who) = 0; 150 SCARG(&bsa, prio) = SCARG(uap, incr); 151 return sys_setpriority(p, &bsa, retval); 152 } 153 154 /* 155 * The old Linux readdir was only able to read one entry at a time, 156 * even though it had a 'count' argument. In fact, the emulation 157 * of the old call was better than the original, because it did handle 158 * the count arg properly. Don't bother with it anymore now, and use 159 * it to distinguish between old and new. The difference is that the 160 * newer one actually does multiple entries, and the reclen field 161 * really is the reclen, not the namelength. 162 */ 163 int 164 linux_sys_readdir(p, v, retval) 165 struct proc *p; 166 void *v; 167 register_t *retval; 168 { 169 struct linux_sys_readdir_args /* { 170 syscallarg(int) fd; 171 syscallarg(struct linux_dirent *) dent; 172 syscallarg(unsigned int) count; 173 } */ *uap = v; 174 175 SCARG(uap, count) = 1; 176 return linux_sys_getdents(p, uap, retval); 177 } 178 179 /* 180 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 181 * need to deal with it. 182 */ 183 int 184 linux_sys_time(p, v, retval) 185 struct proc *p; 186 void *v; 187 register_t *retval; 188 { 189 struct linux_sys_time_args /* { 190 linux_time_t *t; 191 } */ *uap = v; 192 struct timeval atv; 193 linux_time_t tt; 194 int error; 195 196 microtime(&atv); 197 198 tt = atv.tv_sec; 199 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 200 return error; 201 202 retval[0] = tt; 203 return 0; 204 } 205 206 /* 207 * utime(). Do conversion to things that utimes() understands, 208 * and pass it on. 209 */ 210 int 211 linux_sys_utime(p, v, retval) 212 struct proc *p; 213 void *v; 214 register_t *retval; 215 { 216 struct linux_sys_utime_args /* { 217 syscallarg(char *) path; 218 syscallarg(struct linux_utimbuf *)times; 219 } */ *uap = v; 220 caddr_t sg; 221 int error; 222 struct sys_utimes_args ua; 223 struct timeval tv[2], *tvp; 224 struct linux_utimbuf lut; 225 226 sg = stackgap_init(p->p_emul); 227 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 228 229 SCARG(&ua, path) = SCARG(uap, path); 230 231 if (SCARG(uap, times) != NULL) { 232 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 233 return error; 234 tv[0].tv_usec = tv[1].tv_usec = 0; 235 tv[0].tv_sec = lut.l_actime; 236 tv[1].tv_sec = lut.l_modtime; 237 tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv)); 238 if ((error = copyout(tv, tvp, sizeof tv))) 239 return error; 240 SCARG(&ua, tptr) = tvp; 241 } 242 else 243 SCARG(&ua, tptr) = NULL; 244 245 return sys_utimes(p, &ua, retval); 246 } 247 248 /* 249 * waitpid(2). Passed on to the NetBSD call, surrounded by code to 250 * reserve some space for a NetBSD-style wait status, and converting 251 * it to what Linux wants. 252 */ 253 int 254 linux_sys_waitpid(p, v, retval) 255 struct proc *p; 256 void *v; 257 register_t *retval; 258 { 259 struct linux_sys_waitpid_args /* { 260 syscallarg(int) pid; 261 syscallarg(int *) status; 262 syscallarg(int) options; 263 } */ *uap = v; 264 struct sys_wait4_args w4a; 265 int error, *status, tstat; 266 caddr_t sg; 267 268 if (SCARG(uap, status) != NULL) { 269 sg = stackgap_init(p->p_emul); 270 status = (int *) stackgap_alloc(&sg, sizeof status); 271 } else 272 status = NULL; 273 274 SCARG(&w4a, pid) = SCARG(uap, pid); 275 SCARG(&w4a, status) = status; 276 SCARG(&w4a, options) = SCARG(uap, options); 277 SCARG(&w4a, rusage) = NULL; 278 279 if ((error = sys_wait4(p, &w4a, retval))) 280 return error; 281 282 sigdelset(&p->p_siglist, SIGCHLD); 283 284 if (status != NULL) { 285 if ((error = copyin(status, &tstat, sizeof tstat))) 286 return error; 287 288 bsd_to_linux_wstat(&tstat); 289 return copyout(&tstat, SCARG(uap, status), sizeof tstat); 290 } 291 292 return 0; 293 } 294