1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
#DPATCHLEVEL=0
---
# linux-user/syscall.c | 32 +++++++++++++++++++++++++++++---
# 1 file changed, 29 insertions(+), 3 deletions(-)
#
Index: linux-user/syscall.c
===================================================================
--- linux-user/syscall.c.orig
+++ linux-user/syscall.c
@@ -56,6 +56,7 @@
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <qemu-common.h>
+#include <sys/sysctl.h>
#ifdef TARGET_GPROF
#include <sys/gmon.h>
#endif
@@ -5986,9 +5987,34 @@ abi_long do_syscall(void *cpu_env, int n
break;
#endif
case TARGET_NR__sysctl:
- /* We don't implement this, but ENOTDIR is always a safe
- return value. */
- ret = -TARGET_ENOTDIR;
+ {
+ struct __sysctl_args *args = (struct __sysctl_args *) arg1;
+ int *name_target, *name, nlen, *oldlenp, oldlen, newlen, i;
+ void *oldval, *newval;
+
+ name_target = (int *) tswapl((long) args->name);
+ nlen = tswapl(args->nlen);
+ oldval = (void *) tswapl((long) args->oldval);
+ oldlenp = (int *) tswapl((long) args->oldlenp);
+ oldlen = tswapl(*oldlenp);
+ newval = (void *) tswapl((long) args->newval);
+ newlen = tswapl(args->newlen);
+
+ name = alloca(nlen * sizeof (int));
+ for (i = 0; i < nlen; i++)
+ name[i] = tswapl(name_target[i]);
+
+ if (nlen == 2 && name[0] == CTL_KERN && name[1] == KERN_VERSION) {
+ ret = get_errno(
+ sysctl(name, nlen, oldval, &oldlen, newval, newlen));
+ if (!is_error(ret)) {
+ *oldlenp = tswapl(oldlen);
+ }
+ } else {
+ gemu_log("qemu: Unsupported sysctl name\n");
+ ret = -ENOSYS;
+ }
+ }
break;
case TARGET_NR_sched_setparam:
{
|