linux_misc_notalpha.c revision 1.71 1 /* $NetBSD: linux_misc_notalpha.c,v 1.71 2004/09/24 13:10:46 he 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; by Jason R. Thorpe
9 * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center.
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 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.71 2004/09/24 13:10:46 he Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/mman.h>
47 #include <sys/mount.h>
48 #include <sys/malloc.h>
49 #include <sys/mbuf.h>
50 #include <sys/namei.h>
51 #include <sys/proc.h>
52 #include <sys/ptrace.h>
53 #include <sys/resource.h>
54 #include <sys/resourcevar.h>
55 #include <sys/time.h>
56 #include <sys/wait.h>
57
58 #include <sys/sa.h>
59 #include <sys/syscallargs.h>
60
61 #include <compat/linux/common/linux_types.h>
62 #include <compat/linux/common/linux_fcntl.h>
63 #include <compat/linux/common/linux_misc.h>
64 #include <compat/linux/common/linux_mmap.h>
65 #include <compat/linux/common/linux_signal.h>
66 #include <compat/linux/common/linux_util.h>
67
68 #include <compat/linux/linux_syscallargs.h>
69
70 /*
71 * This file contains routines which are used
72 * on every linux architechture except the Alpha.
73 */
74
75 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */
76 /* Not used on: alpha */
77
78 #ifdef DEBUG_LINUX
79 #define DPRINTF(a) uprintf a
80 #else
81 #define DPRINTF(a)
82 #endif
83
84 #ifndef __m68k__
85 static void bsd_to_linux_statfs64(const struct statvfs *,
86 struct linux_statfs64 *);
87 #endif
88
89 /*
90 * Alarm. This is a libc call which uses setitimer(2) in NetBSD.
91 * Fiddle with the timers to make it work.
92 */
93 int
94 linux_sys_alarm(l, v, retval)
95 struct lwp *l;
96 void *v;
97 register_t *retval;
98 {
99 struct linux_sys_alarm_args /* {
100 syscallarg(unsigned int) secs;
101 } */ *uap = v;
102 struct proc *p = l->l_proc;
103 int s;
104 struct itimerval *itp, it;
105 struct ptimer *ptp;
106
107 if (p->p_timers && p->p_timers->pts_timers[ITIMER_REAL])
108 itp = &p->p_timers->pts_timers[ITIMER_REAL]->pt_time;
109 else
110 itp = NULL;
111 s = splclock();
112 /*
113 * Clear any pending timer alarms.
114 */
115 if (itp) {
116 callout_stop(&p->p_timers->pts_timers[ITIMER_REAL]->pt_ch);
117 timerclear(&itp->it_interval);
118 if (timerisset(&itp->it_value) &&
119 timercmp(&itp->it_value, &time, >))
120 timersub(&itp->it_value, &time, &itp->it_value);
121 /*
122 * Return how many seconds were left (rounded up)
123 */
124 retval[0] = itp->it_value.tv_sec;
125 if (itp->it_value.tv_usec)
126 retval[0]++;
127 } else {
128 retval[0] = 0;
129 }
130
131 /*
132 * alarm(0) just resets the timer.
133 */
134 if (SCARG(uap, secs) == 0) {
135 if (itp)
136 timerclear(&itp->it_value);
137 splx(s);
138 return 0;
139 }
140
141 /*
142 * Check the new alarm time for sanity, and set it.
143 */
144 timerclear(&it.it_interval);
145 it.it_value.tv_sec = SCARG(uap, secs);
146 it.it_value.tv_usec = 0;
147 if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) {
148 splx(s);
149 return (EINVAL);
150 }
151
152 if (p->p_timers == NULL)
153 timers_alloc(p);
154 ptp = p->p_timers->pts_timers[ITIMER_REAL];
155 if (ptp == NULL) {
156 ptp = pool_get(&ptimer_pool, PR_WAITOK);
157 ptp->pt_ev.sigev_notify = SIGEV_SIGNAL;
158 ptp->pt_ev.sigev_signo = SIGALRM;
159 ptp->pt_overruns = 0;
160 ptp->pt_proc = p;
161 ptp->pt_type = CLOCK_REALTIME;
162 ptp->pt_entry = CLOCK_REALTIME;
163 callout_init(&ptp->pt_ch);
164 p->p_timers->pts_timers[ITIMER_REAL] = ptp;
165 }
166
167 if (timerisset(&it.it_value)) {
168 /*
169 * Don't need to check hzto() return value, here.
170 * callout_reset() does it for us.
171 */
172 timeradd(&it.it_value, &time, &it.it_value);
173 callout_reset(&ptp->pt_ch, hzto(&it.it_value),
174 realtimerexpire, ptp);
175 }
176 ptp->pt_time = it;
177 splx(s);
178
179 return 0;
180 }
181
182 int
183 linux_sys_nice(l, v, retval)
184 struct lwp *l;
185 void *v;
186 register_t *retval;
187 {
188 struct linux_sys_nice_args /* {
189 syscallarg(int) incr;
190 } */ *uap = v;
191 struct sys_setpriority_args bsa;
192
193 SCARG(&bsa, which) = PRIO_PROCESS;
194 SCARG(&bsa, who) = 0;
195 SCARG(&bsa, prio) = SCARG(uap, incr);
196 return sys_setpriority(l, &bsa, retval);
197 }
198
199 /*
200 * The old Linux readdir was only able to read one entry at a time,
201 * even though it had a 'count' argument. In fact, the emulation
202 * of the old call was better than the original, because it did handle
203 * the count arg properly. Don't bother with it anymore now, and use
204 * it to distinguish between old and new. The difference is that the
205 * newer one actually does multiple entries, and the reclen field
206 * really is the reclen, not the namelength.
207 */
208 int
209 linux_sys_readdir(l, v, retval)
210 struct lwp *l;
211 void *v;
212 register_t *retval;
213 {
214 struct linux_sys_readdir_args /* {
215 syscallarg(int) fd;
216 syscallarg(struct linux_dirent *) dent;
217 syscallarg(unsigned int) count;
218 } */ *uap = v;
219
220 SCARG(uap, count) = 1;
221 return linux_sys_getdents(l, uap, retval);
222 }
223
224 /*
225 * I wonder why Linux has gettimeofday() _and_ time().. Still, we
226 * need to deal with it.
227 */
228 int
229 linux_sys_time(l, v, retval)
230 struct lwp *l;
231 void *v;
232 register_t *retval;
233 {
234 struct linux_sys_time_args /* {
235 linux_time_t *t;
236 } */ *uap = v;
237 struct timeval atv;
238 linux_time_t tt;
239 int error;
240
241 microtime(&atv);
242
243 tt = atv.tv_sec;
244 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt)))
245 return error;
246
247 retval[0] = tt;
248 return 0;
249 }
250
251 /*
252 * utime(). Do conversion to things that utimes() understands,
253 * and pass it on.
254 */
255 int
256 linux_sys_utime(l, v, retval)
257 struct lwp *l;
258 void *v;
259 register_t *retval;
260 {
261 struct linux_sys_utime_args /* {
262 syscallarg(const char *) path;
263 syscallarg(struct linux_utimbuf *)times;
264 } */ *uap = v;
265 struct proc *p = l->l_proc;
266 caddr_t sg;
267 int error;
268 struct sys_utimes_args ua;
269 struct timeval tv[2], *tvp;
270 struct linux_utimbuf lut;
271
272 sg = stackgap_init(p, 0);
273 tvp = (struct timeval *) stackgap_alloc(p, &sg, sizeof(tv));
274 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
275
276 SCARG(&ua, path) = SCARG(uap, path);
277
278 if (SCARG(uap, times) != NULL) {
279 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut)))
280 return error;
281 tv[0].tv_usec = tv[1].tv_usec = 0;
282 tv[0].tv_sec = lut.l_actime;
283 tv[1].tv_sec = lut.l_modtime;
284 if ((error = copyout(tv, tvp, sizeof tv)))
285 return error;
286 SCARG(&ua, tptr) = tvp;
287 }
288 else
289 SCARG(&ua, tptr) = NULL;
290
291 return sys_utimes(l, &ua, retval);
292 }
293
294 /*
295 * waitpid(2). Passed on to the NetBSD call, surrounded by code to
296 * reserve some space for a NetBSD-style wait status, and converting
297 * it to what Linux wants.
298 */
299 int
300 linux_sys_waitpid(l, v, retval)
301 struct lwp *l;
302 void *v;
303 register_t *retval;
304 {
305 struct linux_sys_waitpid_args /* {
306 syscallarg(int) pid;
307 syscallarg(int *) status;
308 syscallarg(int) options;
309 } */ *uap = v;
310 struct proc *p = l->l_proc;
311 struct sys_wait4_args w4a;
312 int error, *status, tstat;
313 caddr_t sg;
314
315 if (SCARG(uap, status) != NULL) {
316 sg = stackgap_init(p, 0);
317 status = (int *) stackgap_alloc(p, &sg, sizeof status);
318 } else
319 status = NULL;
320
321 SCARG(&w4a, pid) = SCARG(uap, pid);
322 SCARG(&w4a, status) = status;
323 SCARG(&w4a, options) = SCARG(uap, options);
324 SCARG(&w4a, rusage) = NULL;
325
326 if ((error = sys_wait4(l, &w4a, retval)))
327 return error;
328
329 sigdelset(&p->p_sigctx.ps_siglist, SIGCHLD);
330
331 if (status != NULL) {
332 if ((error = copyin(status, &tstat, sizeof tstat)))
333 return error;
334
335 bsd_to_linux_wstat(&tstat);
336 return copyout(&tstat, SCARG(uap, status), sizeof tstat);
337 }
338
339 return 0;
340 }
341
342 int
343 linux_sys_setresgid(l, v, retval)
344 struct lwp *l;
345 void *v;
346 register_t *retval;
347 {
348 struct linux_sys_setresgid_args /* {
349 syscallarg(gid_t) rgid;
350 syscallarg(gid_t) egid;
351 syscallarg(gid_t) sgid;
352 } */ *uap = v;
353
354 /*
355 * Note: These checks are a little different than the NetBSD
356 * setregid(2) call performs. This precisely follows the
357 * behavior of the Linux kernel.
358 */
359 return do_setresgid(l, SCARG(uap,rgid), SCARG(uap, egid),
360 SCARG(uap, sgid),
361 ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
362 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
363 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
364 }
365
366 int
367 linux_sys_getresgid(l, v, retval)
368 struct lwp *l;
369 void *v;
370 register_t *retval;
371 {
372 struct linux_sys_getresgid_args /* {
373 syscallarg(gid_t *) rgid;
374 syscallarg(gid_t *) egid;
375 syscallarg(gid_t *) sgid;
376 } */ *uap = v;
377 struct proc *p = l->l_proc;
378 struct pcred *pc = p->p_cred;
379 int error;
380
381 /*
382 * Linux copies these values out to userspace like so:
383 *
384 * 1. Copy out rgid.
385 * 2. If that succeeds, copy out egid.
386 * 3. If both of those succeed, copy out sgid.
387 */
388 if ((error = copyout(&pc->p_rgid, SCARG(uap, rgid),
389 sizeof(gid_t))) != 0)
390 return (error);
391
392 if ((error = copyout(&pc->pc_ucred->cr_gid, SCARG(uap, egid),
393 sizeof(gid_t))) != 0)
394 return (error);
395
396 return (copyout(&pc->p_svgid, SCARG(uap, sgid), sizeof(gid_t)));
397 }
398
399 /*
400 * I wonder why Linux has settimeofday() _and_ stime().. Still, we
401 * need to deal with it.
402 */
403 int
404 linux_sys_stime(l, v, retval)
405 struct lwp *l;
406 void *v;
407 register_t *retval;
408 {
409 struct linux_sys_time_args /* {
410 linux_time_t *t;
411 } */ *uap = v;
412 struct proc *p = l->l_proc;
413 struct timeval atv;
414 linux_time_t tt;
415 int error;
416
417 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
418 return (error);
419
420 if ((error = copyin(&tt, SCARG(uap, t), sizeof tt)) != 0)
421 return error;
422
423 atv.tv_sec = tt;
424 atv.tv_usec = 0;
425
426 if ((error = settime(&atv)))
427 return (error);
428
429 return 0;
430 }
431
432 #ifndef __m68k__
433 /*
434 * Convert NetBSD statvfs structure to Linux statfs64 structure.
435 * See comments in bsd_to_linux_statfs() for further background.
436 * We can safely pass correct bsize and frsize here, since Linux glibc
437 * statvfs() doesn't use statfs64().
438 */
439 static void
440 bsd_to_linux_statfs64(bsp, lsp)
441 const struct statvfs *bsp;
442 struct linux_statfs64 *lsp;
443 {
444 int i, div;
445
446 for (i = 0; i < linux_fstypes_cnt; i++) {
447 if (strcmp(bsp->f_fstypename, linux_fstypes[i].bsd) == 0) {
448 lsp->l_ftype = linux_fstypes[i].linux;
449 break;
450 }
451 }
452
453 if (i == linux_fstypes_cnt) {
454 DPRINTF(("unhandled fstype in linux emulation: %s\n",
455 bsp->f_fstypename));
456 lsp->l_ftype = LINUX_DEFAULT_SUPER_MAGIC;
457 }
458
459 div = bsp->f_bsize / bsp->f_frsize;
460 lsp->l_fbsize = bsp->f_bsize;
461 lsp->l_ffrsize = bsp->f_frsize;
462 lsp->l_fblocks = bsp->f_blocks / div;
463 lsp->l_fbfree = bsp->f_bfree / div;
464 lsp->l_fbavail = bsp->f_bavail / div;
465 lsp->l_ffiles = bsp->f_files;
466 lsp->l_fffree = bsp->f_ffree / div;
467 /* Linux sets the fsid to 0..., we don't */
468 lsp->l_ffsid.val[0] = bsp->f_fsidx.__fsid_val[0];
469 lsp->l_ffsid.val[1] = bsp->f_fsidx.__fsid_val[1];
470 lsp->l_fnamelen = bsp->f_namemax;
471 (void)memset(lsp->l_fspare, 0, sizeof(lsp->l_fspare));
472 }
473
474 /*
475 * Implement the fs stat functions. Straightforward.
476 */
477 int
478 linux_sys_statfs64(l, v, retval)
479 struct lwp *l;
480 void *v;
481 register_t *retval;
482 {
483 struct linux_sys_statfs64_args /* {
484 syscallarg(const char *) path;
485 syscallarg(size_t) sz;
486 syscallarg(struct linux_statfs64 *) sp;
487 } */ *uap = v;
488 struct proc *p = l->l_proc;
489 struct statvfs btmp, *bsp;
490 struct linux_statfs64 ltmp;
491 struct sys_statvfs1_args bsa;
492 caddr_t sg;
493 int error;
494
495 if (SCARG(uap, sz) != sizeof ltmp)
496 return (EINVAL);
497
498 sg = stackgap_init(p, 0);
499 bsp = (struct statvfs *) stackgap_alloc(p, &sg, sizeof (struct statvfs));
500
501 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
502
503 SCARG(&bsa, path) = SCARG(uap, path);
504 SCARG(&bsa, buf) = bsp;
505 SCARG(&bsa, flags) = ST_WAIT;
506
507 if ((error = sys_statvfs1(l, &bsa, retval)))
508 return error;
509
510 if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
511 return error;
512
513 bsd_to_linux_statfs64(&btmp, <mp);
514
515 return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
516 }
517
518 int
519 linux_sys_fstatfs64(l, v, retval)
520 struct lwp *l;
521 void *v;
522 register_t *retval;
523 {
524 struct linux_sys_fstatfs64_args /* {
525 syscallarg(int) fd;
526 syscallarg(size_t) sz;
527 syscallarg(struct linux_statfs64 *) sp;
528 } */ *uap = v;
529 struct proc *p = l->l_proc;
530 struct statvfs btmp, *bsp;
531 struct linux_statfs64 ltmp;
532 struct sys_fstatvfs1_args bsa;
533 caddr_t sg;
534 int error;
535
536 if (SCARG(uap, sz) != sizeof ltmp)
537 return (EINVAL);
538
539 sg = stackgap_init(p, 0);
540 bsp = (struct statvfs *) stackgap_alloc(p, &sg, sizeof (struct statvfs));
541
542 SCARG(&bsa, fd) = SCARG(uap, fd);
543 SCARG(&bsa, buf) = bsp;
544 SCARG(&bsa, flags) = ST_WAIT;
545
546 if ((error = sys_fstatvfs1(l, &bsa, retval)))
547 return error;
548
549 if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
550 return error;
551
552 bsd_to_linux_statfs64(&btmp, <mp);
553
554 return copyout((caddr_t) <mp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
555 }
556 #endif /* !__m68k__ */
557