aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/os-Linux
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/Makefile13
-rw-r--r--arch/um/os-Linux/drivers/Makefile13
-rw-r--r--arch/um/os-Linux/drivers/etap.h27
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c119
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c240
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h32
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c104
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c225
-rw-r--r--arch/um/os-Linux/elf_aux.c66
-rw-r--r--arch/um/os-Linux/file.c680
-rw-r--r--arch/um/os-Linux/include/file.h22
-rw-r--r--arch/um/os-Linux/process.c171
-rw-r--r--arch/um/os-Linux/signal.c48
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile10
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c132
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile10
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c81
-rw-r--r--arch/um/os-Linux/time.c21
-rw-r--r--arch/um/os-Linux/tty.c61
-rw-r--r--arch/um/os-Linux/user_syms.c95
-rw-r--r--arch/um/os-Linux/util/Makefile4
-rw-r--r--arch/um/os-Linux/util/mk_user_constants.c29
22 files changed, 2203 insertions, 0 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
new file mode 100644
index 000000000000..4ddf540284ce
--- /dev/null
+++ b/arch/um/os-Linux/Makefile
@@ -0,0 +1,13 @@
1#
2# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3# Licensed under the GPL
4#
5
6obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \
7 sys-$(SUBARCH)/
8
9USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o
10
11CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
12
13include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/drivers/Makefile b/arch/um/os-Linux/drivers/Makefile
new file mode 100644
index 000000000000..6c546dc9222b
--- /dev/null
+++ b/arch/um/os-Linux/drivers/Makefile
@@ -0,0 +1,13 @@
1#
2# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
3# Licensed under the GPL
4#
5
6ethertap-objs := ethertap_kern.o ethertap_user.o
7tuntap-objs := tuntap_kern.o tuntap_user.o
8
9obj-y =
10obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o
11obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o
12
13include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h
new file mode 100644
index 000000000000..b84f6c4740f7
--- /dev/null
+++ b/arch/um/os-Linux/drivers/etap.h
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "net_user.h"
7
8struct ethertap_data {
9 char *dev_name;
10 char *gate_addr;
11 int data_fd;
12 int control_fd;
13 void *dev;
14};
15
16extern struct net_user_info ethertap_user_info;
17
18/*
19 * Overrides for Emacs so that we follow Linus's tabbing style.
20 * Emacs will notice this stuff at the end of the file and automatically
21 * adjust the settings for this buffer only. This must remain at the end
22 * of the file.
23 * ---------------------------------------------------------------------------
24 * Local variables:
25 * c-file-style: "linux"
26 * End:
27 */
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
new file mode 100644
index 000000000000..6ae4b19d9f50
--- /dev/null
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -0,0 +1,119 @@
1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL.
6 */
7
8#include "linux/init.h"
9#include "linux/netdevice.h"
10#include "linux/etherdevice.h"
11#include "net_kern.h"
12#include "net_user.h"
13#include "etap.h"
14
15struct ethertap_init {
16 char *dev_name;
17 char *gate_addr;
18};
19
20static void etap_init(struct net_device *dev, void *data)
21{
22 struct uml_net_private *pri;
23 struct ethertap_data *epri;
24 struct ethertap_init *init = data;
25
26 pri = dev->priv;
27 epri = (struct ethertap_data *) pri->user;
28 epri->dev_name = init->dev_name;
29 epri->gate_addr = init->gate_addr;
30 epri->data_fd = -1;
31 epri->control_fd = -1;
32 epri->dev = dev;
33
34 printk("ethertap backend - %s", epri->dev_name);
35 if (epri->gate_addr != NULL)
36 printk(", IP = %s", epri->gate_addr);
37 printk("\n");
38}
39
40static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp)
41{
42 int len;
43
44 *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP);
45 if(*skb == NULL) return(-ENOMEM);
46 len = net_recvfrom(fd, (*skb)->mac.raw,
47 (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP);
48 if(len <= 0) return(len);
49 skb_pull(*skb, 2);
50 len -= 2;
51 return(len);
52}
53
54static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
55{
56 if(skb_headroom(*skb) < 2){
57 struct sk_buff *skb2;
58
59 skb2 = skb_realloc_headroom(*skb, 2);
60 dev_kfree_skb(*skb);
61 if (skb2 == NULL) return(-ENOMEM);
62 *skb = skb2;
63 }
64 skb_push(*skb, 2);
65 return(net_send(fd, (*skb)->data, (*skb)->len));
66}
67
68struct net_kern_info ethertap_kern_info = {
69 .init = etap_init,
70 .protocol = eth_protocol,
71 .read = etap_read,
72 .write = etap_write,
73};
74
75int ethertap_setup(char *str, char **mac_out, void *data)
76{
77 struct ethertap_init *init = data;
78
79 *init = ((struct ethertap_init)
80 { .dev_name = NULL,
81 .gate_addr = NULL });
82 if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out,
83 &init->gate_addr))
84 return(0);
85 if(init->dev_name == NULL){
86 printk("ethertap_setup : Missing tap device name\n");
87 return(0);
88 }
89
90 return(1);
91}
92
93static struct transport ethertap_transport = {
94 .list = LIST_HEAD_INIT(ethertap_transport.list),
95 .name = "ethertap",
96 .setup = ethertap_setup,
97 .user = &ethertap_user_info,
98 .kern = &ethertap_kern_info,
99 .private_size = sizeof(struct ethertap_data),
100};
101
102static int register_ethertap(void)
103{
104 register_transport(&ethertap_transport);
105 return(1);
106}
107
108__initcall(register_ethertap);
109
110/*
111 * Overrides for Emacs so that we follow Linus's tabbing style.
112 * Emacs will notice this stuff at the end of the file and automatically
113 * adjust the settings for this buffer only. This must remain at the end
114 * of the file.
115 * ---------------------------------------------------------------------------
116 * Local variables:
117 * c-file-style: "linux"
118 * End:
119 */
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
new file mode 100644
index 000000000000..cd4d6544da71
--- /dev/null
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -0,0 +1,240 @@
1/*
2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
3 * James Leu (jleu@mindspring.net).
4 * Copyright (C) 2001 by various other people who didn't put their name here.
5 * Licensed under the GPL.
6 */
7
8#include <stdio.h>
9#include <unistd.h>
10#include <stddef.h>
11#include <stdlib.h>
12#include <sys/errno.h>
13#include <sys/socket.h>
14#include <sys/wait.h>
15#include <sys/un.h>
16#include <net/if.h>
17#include "user.h"
18#include "kern_util.h"
19#include "user_util.h"
20#include "net_user.h"
21#include "etap.h"
22#include "helper.h"
23#include "os.h"
24
25#define MAX_PACKET ETH_MAX_PACKET
26
27void etap_user_init(void *data, void *dev)
28{
29 struct ethertap_data *pri = data;
30
31 pri->dev = dev;
32}
33
34struct addr_change {
35 enum { ADD_ADDR, DEL_ADDR } what;
36 unsigned char addr[4];
37 unsigned char netmask[4];
38};
39
40static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
41 int fd)
42{
43 struct addr_change change;
44 void *output;
45 int n;
46
47 change.what = op;
48 memcpy(change.addr, addr, sizeof(change.addr));
49 memcpy(change.netmask, netmask, sizeof(change.netmask));
50 n = os_write_file(fd, &change, sizeof(change));
51 if(n != sizeof(change))
52 printk("etap_change - request failed, err = %d\n", -n);
53 output = um_kmalloc(page_size());
54 if(output == NULL)
55 printk("etap_change : Failed to allocate output buffer\n");
56 read_output(fd, output, page_size());
57 if(output != NULL){
58 printk("%s", output);
59 kfree(output);
60 }
61}
62
63static void etap_open_addr(unsigned char *addr, unsigned char *netmask,
64 void *arg)
65{
66 etap_change(ADD_ADDR, addr, netmask, *((int *) arg));
67}
68
69static void etap_close_addr(unsigned char *addr, unsigned char *netmask,
70 void *arg)
71{
72 etap_change(DEL_ADDR, addr, netmask, *((int *) arg));
73}
74
75struct etap_pre_exec_data {
76 int control_remote;
77 int control_me;
78 int data_me;
79};
80
81static void etap_pre_exec(void *arg)
82{
83 struct etap_pre_exec_data *data = arg;
84
85 dup2(data->control_remote, 1);
86 os_close_file(data->data_me);
87 os_close_file(data->control_me);
88}
89
90static int etap_tramp(char *dev, char *gate, int control_me,
91 int control_remote, int data_me, int data_remote)
92{
93 struct etap_pre_exec_data pe_data;
94 int pid, status, err, n;
95 char version_buf[sizeof("nnnnn\0")];
96 char data_fd_buf[sizeof("nnnnnn\0")];
97 char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
98 char *setup_args[] = { "uml_net", version_buf, "ethertap", dev,
99 data_fd_buf, gate_buf, NULL };
100 char *nosetup_args[] = { "uml_net", version_buf, "ethertap",
101 dev, data_fd_buf, NULL };
102 char **args, c;
103
104 sprintf(data_fd_buf, "%d", data_remote);
105 sprintf(version_buf, "%d", UML_NET_VERSION);
106 if(gate != NULL){
107 strcpy(gate_buf, gate);
108 args = setup_args;
109 }
110 else args = nosetup_args;
111
112 err = 0;
113 pe_data.control_remote = control_remote;
114 pe_data.control_me = control_me;
115 pe_data.data_me = data_me;
116 pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
117
118 if(pid < 0) err = pid;
119 os_close_file(data_remote);
120 os_close_file(control_remote);
121 n = os_read_file(control_me, &c, sizeof(c));
122 if(n != sizeof(c)){
123 printk("etap_tramp : read of status failed, err = %d\n", -n);
124 return(-EINVAL);
125 }
126 if(c != 1){
127 printk("etap_tramp : uml_net failed\n");
128 err = -EINVAL;
129 CATCH_EINTR(n = waitpid(pid, &status, 0));
130 if(n < 0)
131 err = -errno;
132 else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
133 printk("uml_net didn't exit with status 1\n");
134 }
135 return(err);
136}
137
138static int etap_open(void *data)
139{
140 struct ethertap_data *pri = data;
141 char *output;
142 int data_fds[2], control_fds[2], err, output_len;
143
144 err = tap_open_common(pri->dev, pri->gate_addr);
145 if(err) return(err);
146
147 err = os_pipe(data_fds, 0, 0);
148 if(err < 0){
149 printk("data os_pipe failed - err = %d\n", -err);
150 return(err);
151 }
152
153 err = os_pipe(control_fds, 1, 0);
154 if(err < 0){
155 printk("control os_pipe failed - err = %d\n", -err);
156 return(err);
157 }
158
159 err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0],
160 control_fds[1], data_fds[0], data_fds[1]);
161 output_len = page_size();
162 output = um_kmalloc(output_len);
163 read_output(control_fds[0], output, output_len);
164
165 if(output == NULL)
166 printk("etap_open : failed to allocate output buffer\n");
167 else {
168 printk("%s", output);
169 kfree(output);
170 }
171
172 if(err < 0){
173 printk("etap_tramp failed - err = %d\n", -err);
174 return(err);
175 }
176
177 pri->data_fd = data_fds[0];
178 pri->control_fd = control_fds[0];
179 iter_addresses(pri->dev, etap_open_addr, &pri->control_fd);
180 return(data_fds[0]);
181}
182
183static void etap_close(int fd, void *data)
184{
185 struct ethertap_data *pri = data;
186
187 iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
188 os_close_file(fd);
189 os_shutdown_socket(pri->data_fd, 1, 1);
190 os_close_file(pri->data_fd);
191 pri->data_fd = -1;
192 os_close_file(pri->control_fd);
193 pri->control_fd = -1;
194}
195
196static int etap_set_mtu(int mtu, void *data)
197{
198 return(mtu);
199}
200
201static void etap_add_addr(unsigned char *addr, unsigned char *netmask,
202 void *data)
203{
204 struct ethertap_data *pri = data;
205
206 tap_check_ips(pri->gate_addr, addr);
207 if(pri->control_fd == -1) return;
208 etap_open_addr(addr, netmask, &pri->control_fd);
209}
210
211static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
212 void *data)
213{
214 struct ethertap_data *pri = data;
215
216 if(pri->control_fd == -1) return;
217 etap_close_addr(addr, netmask, &pri->control_fd);
218}
219
220struct net_user_info ethertap_user_info = {
221 .init = etap_user_init,
222 .open = etap_open,
223 .close = etap_close,
224 .remove = NULL,
225 .set_mtu = etap_set_mtu,
226 .add_address = etap_add_addr,
227 .delete_address = etap_del_addr,
228 .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP
229};
230
231/*
232 * Overrides for Emacs so that we follow Linus's tabbing style.
233 * Emacs will notice this stuff at the end of the file and automatically
234 * adjust the settings for this buffer only. This must remain at the end
235 * of the file.
236 * ---------------------------------------------------------------------------
237 * Local variables:
238 * c-file-style: "linux"
239 * End:
240 */
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h
new file mode 100644
index 000000000000..25d4a2868814
--- /dev/null
+++ b/arch/um/os-Linux/drivers/tuntap.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __UM_TUNTAP_H
7#define __UM_TUNTAP_H
8
9#include "net_user.h"
10
11struct tuntap_data {
12 char *dev_name;
13 int fixed_config;
14 char *gate_addr;
15 int fd;
16 void *dev;
17};
18
19extern struct net_user_info tuntap_user_info;
20
21#endif
22
23/*
24 * Overrides for Emacs so that we follow Linus's tabbing style.
25 * Emacs will notice this stuff at the end of the file and automatically
26 * adjust the settings for this buffer only. This must remain at the end
27 * of the file.
28 * ---------------------------------------------------------------------------
29 * Local variables:
30 * c-file-style: "linux"
31 * End:
32 */
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
new file mode 100644
index 000000000000..4202b9ebad4c
--- /dev/null
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -0,0 +1,104 @@
1/*
2 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include "linux/stddef.h"
7#include "linux/netdevice.h"
8#include "linux/etherdevice.h"
9#include "linux/skbuff.h"
10#include "linux/init.h"
11#include "asm/errno.h"
12#include "net_kern.h"
13#include "net_user.h"
14#include "tuntap.h"
15
16struct tuntap_init {
17 char *dev_name;
18 char *gate_addr;
19};
20
21static void tuntap_init(struct net_device *dev, void *data)
22{
23 struct uml_net_private *pri;
24 struct tuntap_data *tpri;
25 struct tuntap_init *init = data;
26
27 pri = dev->priv;
28 tpri = (struct tuntap_data *) pri->user;
29 tpri->dev_name = init->dev_name;
30 tpri->fixed_config = (init->dev_name != NULL);
31 tpri->gate_addr = init->gate_addr;
32 tpri->fd = -1;
33 tpri->dev = dev;
34
35 printk("TUN/TAP backend - ");
36 if (tpri->gate_addr != NULL)
37 printk("IP = %s", tpri->gate_addr);
38 printk("\n");
39}
40
41static int tuntap_read(int fd, struct sk_buff **skb,
42 struct uml_net_private *lp)
43{
44 *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
45 if(*skb == NULL) return(-ENOMEM);
46 return(net_read(fd, (*skb)->mac.raw,
47 (*skb)->dev->mtu + ETH_HEADER_OTHER));
48}
49
50static int tuntap_write(int fd, struct sk_buff **skb,
51 struct uml_net_private *lp)
52{
53 return(net_write(fd, (*skb)->data, (*skb)->len));
54}
55
56struct net_kern_info tuntap_kern_info = {
57 .init = tuntap_init,
58 .protocol = eth_protocol,
59 .read = tuntap_read,
60 .write = tuntap_write,
61};
62
63int tuntap_setup(char *str, char **mac_out, void *data)
64{
65 struct tuntap_init *init = data;
66
67 *init = ((struct tuntap_init)
68 { .dev_name = NULL,
69 .gate_addr = NULL });
70 if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out,
71 &init->gate_addr))
72 return(0);
73
74 return(1);
75}
76
77static struct transport tuntap_transport = {
78 .list = LIST_HEAD_INIT(tuntap_transport.list),
79 .name = "tuntap",
80 .setup = tuntap_setup,
81 .user = &tuntap_user_info,
82 .kern = &tuntap_kern_info,
83 .private_size = sizeof(struct tuntap_data),
84 .setup_size = sizeof(struct tuntap_init),
85};
86
87static int register_tuntap(void)
88{
89 register_transport(&tuntap_transport);
90 return(1);
91}
92
93__initcall(register_tuntap);
94
95/*
96 * Overrides for Emacs so that we follow Linus's tabbing style.
97 * Emacs will notice this stuff at the end of the file and automatically
98 * adjust the settings for this buffer only. This must remain at the end
99 * of the file.
100 * ---------------------------------------------------------------------------
101 * Local variables:
102 * c-file-style: "linux"
103 * End:
104 */
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
new file mode 100644
index 000000000000..4b83c6c3f48d
--- /dev/null
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -0,0 +1,225 @@
1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <stddef.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <errno.h>
11#include <sys/wait.h>
12#include <sys/socket.h>
13#include <sys/un.h>
14#include <sys/uio.h>
15#include <sys/ioctl.h>
16#include <net/if.h>
17#include <linux/if_tun.h>
18#include "net_user.h"
19#include "tuntap.h"
20#include "kern_util.h"
21#include "user_util.h"
22#include "user.h"
23#include "helper.h"
24#include "os.h"
25
26#define MAX_PACKET ETH_MAX_PACKET
27
28void tuntap_user_init(void *data, void *dev)
29{
30 struct tuntap_data *pri = data;
31
32 pri->dev = dev;
33}
34
35static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask,
36 void *data)
37{
38 struct tuntap_data *pri = data;
39
40 tap_check_ips(pri->gate_addr, addr);
41 if((pri->fd == -1) || pri->fixed_config) return;
42 open_addr(addr, netmask, pri->dev_name);
43}
44
45static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask,
46 void *data)
47{
48 struct tuntap_data *pri = data;
49
50 if((pri->fd == -1) || pri->fixed_config) return;
51 close_addr(addr, netmask, pri->dev_name);
52}
53
54struct tuntap_pre_exec_data {
55 int stdout;
56 int close_me;
57};
58
59static void tuntap_pre_exec(void *arg)
60{
61 struct tuntap_pre_exec_data *data = arg;
62
63 dup2(data->stdout, 1);
64 os_close_file(data->close_me);
65}
66
67static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
68 char *buffer, int buffer_len, int *used_out)
69{
70 struct tuntap_pre_exec_data data;
71 char version_buf[sizeof("nnnnn\0")];
72 char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate,
73 NULL };
74 char buf[CMSG_SPACE(sizeof(*fd_out))];
75 struct msghdr msg;
76 struct cmsghdr *cmsg;
77 struct iovec iov;
78 int pid, n;
79
80 sprintf(version_buf, "%d", UML_NET_VERSION);
81
82 data.stdout = remote;
83 data.close_me = me;
84
85 pid = run_helper(tuntap_pre_exec, &data, argv, NULL);
86
87 if(pid < 0) return(-pid);
88
89 os_close_file(remote);
90
91 msg.msg_name = NULL;
92 msg.msg_namelen = 0;
93 if(buffer != NULL){
94 iov = ((struct iovec) { buffer, buffer_len });
95 msg.msg_iov = &iov;
96 msg.msg_iovlen = 1;
97 }
98 else {
99 msg.msg_iov = NULL;
100 msg.msg_iovlen = 0;
101 }
102 msg.msg_control = buf;
103 msg.msg_controllen = sizeof(buf);
104 msg.msg_flags = 0;
105 n = recvmsg(me, &msg, 0);
106 *used_out = n;
107 if(n < 0){
108 printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
109 errno);
110 return(-errno);
111 }
112 CATCH_EINTR(waitpid(pid, NULL, 0));
113
114 cmsg = CMSG_FIRSTHDR(&msg);
115 if(cmsg == NULL){
116 printk("tuntap_open_tramp : didn't receive a message\n");
117 return(-EINVAL);
118 }
119 if((cmsg->cmsg_level != SOL_SOCKET) ||
120 (cmsg->cmsg_type != SCM_RIGHTS)){
121 printk("tuntap_open_tramp : didn't receive a descriptor\n");
122 return(-EINVAL);
123 }
124 *fd_out = ((int *) CMSG_DATA(cmsg))[0];
125 return(0);
126}
127
128static int tuntap_open(void *data)
129{
130 struct ifreq ifr;
131 struct tuntap_data *pri = data;
132 char *output, *buffer;
133 int err, fds[2], len, used;
134
135 err = tap_open_common(pri->dev, pri->gate_addr);
136 if(err < 0)
137 return(err);
138
139 if(pri->fixed_config){
140 pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
141 if(pri->fd < 0){
142 printk("Failed to open /dev/net/tun, err = %d\n",
143 -pri->fd);
144 return(pri->fd);
145 }
146 memset(&ifr, 0, sizeof(ifr));
147 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
148 strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
149 if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
150 printk("TUNSETIFF failed, errno = %d\n", errno);
151 os_close_file(pri->fd);
152 return(-errno);
153 }
154 }
155 else {
156 err = os_pipe(fds, 0, 0);
157 if(err < 0){
158 printk("tuntap_open : os_pipe failed - err = %d\n",
159 -err);
160 return(err);
161 }
162
163 buffer = get_output_buffer(&len);
164 if(buffer != NULL) len--;
165 used = 0;
166
167 err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0],
168 fds[1], buffer, len, &used);
169
170 output = buffer;
171 if(err < 0) {
172 printk("%s", output);
173 free_output_buffer(buffer);
174 printk("tuntap_open_tramp failed - err = %d\n", -err);
175 return(err);
176 }
177
178 pri->dev_name = uml_strdup(buffer);
179 output += IFNAMSIZ;
180 printk("%s", output);
181 free_output_buffer(buffer);
182
183 os_close_file(fds[0]);
184 iter_addresses(pri->dev, open_addr, pri->dev_name);
185 }
186
187 return(pri->fd);
188}
189
190static void tuntap_close(int fd, void *data)
191{
192 struct tuntap_data *pri = data;
193
194 if(!pri->fixed_config)
195 iter_addresses(pri->dev, close_addr, pri->dev_name);
196 os_close_file(fd);
197 pri->fd = -1;
198}
199
200static int tuntap_set_mtu(int mtu, void *data)
201{
202 return(mtu);
203}
204
205struct net_user_info tuntap_user_info = {
206 .init = tuntap_user_init,
207 .open = tuntap_open,
208 .close = tuntap_close,
209 .remove = NULL,
210 .set_mtu = tuntap_set_mtu,
211 .add_address = tuntap_add_addr,
212 .delete_address = tuntap_del_addr,
213 .max_packet = MAX_PACKET
214};
215
216/*
217 * Overrides for Emacs so that we follow Linus's tabbing style.
218 * Emacs will notice this stuff at the end of the file and automatically
219 * adjust the settings for this buffer only. This must remain at the end
220 * of the file.
221 * ---------------------------------------------------------------------------
222 * Local variables:
223 * c-file-style: "linux"
224 * End:
225 */
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
new file mode 100644
index 000000000000..9aee0b62ebca
--- /dev/null
+++ b/arch/um/os-Linux/elf_aux.c
@@ -0,0 +1,66 @@
1/*
2 * arch/um/kernel/elf_aux.c
3 *
4 * Scan the Elf auxiliary vector provided by the host to extract
5 * information about vsyscall-page, etc.
6 *
7 * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
8 * Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com)
9 */
10#include <elf.h>
11#include <stddef.h>
12#include "init.h"
13#include "elf_user.h"
14
15#if ELF_CLASS == ELFCLASS32
16typedef Elf32_auxv_t elf_auxv_t;
17#else
18typedef Elf64_auxv_t elf_auxv_t;
19#endif
20
21char * elf_aux_platform;
22long elf_aux_hwcap;
23
24unsigned long vsyscall_ehdr;
25unsigned long vsyscall_end;
26
27unsigned long __kernel_vsyscall;
28
29__init void scan_elf_aux( char **envp)
30{
31 long page_size = 0;
32 elf_auxv_t * auxv;
33
34 while ( *envp++ != NULL) ;
35
36 for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
37 switch ( auxv->a_type ) {
38 case AT_SYSINFO:
39 __kernel_vsyscall = auxv->a_un.a_val;
40 break;
41 case AT_SYSINFO_EHDR:
42 vsyscall_ehdr = auxv->a_un.a_val;
43 break;
44 case AT_HWCAP:
45 elf_aux_hwcap = auxv->a_un.a_val;
46 break;
47 case AT_PLATFORM:
48 elf_aux_platform = auxv->a_un.a_ptr;
49 break;
50 case AT_PAGESZ:
51 page_size = auxv->a_un.a_val;
52 break;
53 }
54 }
55 if ( ! __kernel_vsyscall || ! vsyscall_ehdr ||
56 ! elf_aux_hwcap || ! elf_aux_platform ||
57 ! page_size || (vsyscall_ehdr % page_size) ) {
58 __kernel_vsyscall = 0;
59 vsyscall_ehdr = 0;
60 elf_aux_hwcap = 0;
61 elf_aux_platform = "i586";
62 }
63 else {
64 vsyscall_end = vsyscall_ehdr + page_size;
65 }
66}
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
new file mode 100644
index 000000000000..77d4066d1af8
--- /dev/null
+++ b/arch/um/os-Linux/file.c
@@ -0,0 +1,680 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <unistd.h>
8#include <errno.h>
9#include <fcntl.h>
10#include <signal.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <sys/socket.h>
14#include <sys/un.h>
15#include <sys/ioctl.h>
16#include <sys/mount.h>
17#include <sys/uio.h>
18#include "os.h"
19#include "user.h"
20#include "kern_util.h"
21
22static void copy_stat(struct uml_stat *dst, struct stat64 *src)
23{
24 *dst = ((struct uml_stat) {
25 .ust_dev = src->st_dev, /* device */
26 .ust_ino = src->st_ino, /* inode */
27 .ust_mode = src->st_mode, /* protection */
28 .ust_nlink = src->st_nlink, /* number of hard links */
29 .ust_uid = src->st_uid, /* user ID of owner */
30 .ust_gid = src->st_gid, /* group ID of owner */
31 .ust_size = src->st_size, /* total size, in bytes */
32 .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
33 .ust_blocks = src->st_blocks, /* number of blocks allocated */
34 .ust_atime = src->st_atime, /* time of last access */
35 .ust_mtime = src->st_mtime, /* time of last modification */
36 .ust_ctime = src->st_ctime, /* time of last change */
37 });
38}
39
40int os_stat_fd(const int fd, struct uml_stat *ubuf)
41{
42 struct stat64 sbuf;
43 int err;
44
45 do {
46 err = fstat64(fd, &sbuf);
47 } while((err < 0) && (errno == EINTR)) ;
48
49 if(err < 0)
50 return(-errno);
51
52 if(ubuf != NULL)
53 copy_stat(ubuf, &sbuf);
54 return(err);
55}
56
57int os_stat_file(const char *file_name, struct uml_stat *ubuf)
58{
59 struct stat64 sbuf;
60 int err;
61
62 do {
63 err = stat64(file_name, &sbuf);
64 } while((err < 0) && (errno == EINTR)) ;
65
66 if(err < 0)
67 return(-errno);
68
69 if(ubuf != NULL)
70 copy_stat(ubuf, &sbuf);
71 return(err);
72}
73
74int os_access(const char* file, int mode)
75{
76 int amode, err;
77
78 amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
79 (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
80
81 err = access(file, amode);
82 if(err < 0)
83 return(-errno);
84
85 return(0);
86}
87
88void os_print_error(int error, const char* str)
89{
90 errno = error < 0 ? -error : error;
91
92 perror(str);
93}
94
95/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
96int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
97{
98 int err;
99
100 err = ioctl(fd, cmd, arg);
101 if(err < 0)
102 return(-errno);
103
104 return(err);
105}
106
107int os_window_size(int fd, int *rows, int *cols)
108{
109 struct winsize size;
110
111 if(ioctl(fd, TIOCGWINSZ, &size) < 0)
112 return(-errno);
113
114 *rows = size.ws_row;
115 *cols = size.ws_col;
116
117 return(0);
118}
119
120int os_new_tty_pgrp(int fd, int pid)
121{
122 if(ioctl(fd, TIOCSCTTY, 0) < 0){
123 printk("TIOCSCTTY failed, errno = %d\n", errno);
124 return(-errno);
125 }
126
127 if(tcsetpgrp(fd, pid) < 0){
128 printk("tcsetpgrp failed, errno = %d\n", errno);
129 return(-errno);
130 }
131
132 return(0);
133}
134
135/* FIXME: ensure namebuf in os_get_if_name is big enough */
136int os_get_ifname(int fd, char* namebuf)
137{
138 if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
139 return(-errno);
140
141 return(0);
142}
143
144int os_set_slip(int fd)
145{
146 int disc, sencap;
147
148 disc = N_SLIP;
149 if(ioctl(fd, TIOCSETD, &disc) < 0){
150 printk("Failed to set slip line discipline - "
151 "errno = %d\n", errno);
152 return(-errno);
153 }
154
155 sencap = 0;
156 if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
157 printk("Failed to set slip encapsulation - "
158 "errno = %d\n", errno);
159 return(-errno);
160 }
161
162 return(0);
163}
164
165int os_set_owner(int fd, int pid)
166{
167 if(fcntl(fd, F_SETOWN, pid) < 0){
168 int save_errno = errno;
169
170 if(fcntl(fd, F_GETOWN, 0) != pid)
171 return(-save_errno);
172 }
173
174 return(0);
175}
176
177/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
178int os_sigio_async(int master, int slave)
179{
180 int flags;
181
182 flags = fcntl(master, F_GETFL);
183 if(flags < 0) {
184 printk("fcntl F_GETFL failed, errno = %d\n", errno);
185 return(-errno);
186 }
187
188 if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
189 (fcntl(master, F_SETOWN, os_getpid()) < 0)){
190 printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n",
191 errno);
192 return(-errno);
193 }
194
195 if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
196 printk("fcntl F_SETFL failed, errno = %d\n", errno);
197 return(-errno);
198 }
199
200 return(0);
201}
202
203int os_mode_fd(int fd, int mode)
204{
205 int err;
206
207 do {
208 err = fchmod(fd, mode);
209 } while((err < 0) && (errno==EINTR)) ;
210
211 if(err < 0)
212 return(-errno);
213
214 return(0);
215}
216
217int os_file_type(char *file)
218{
219 struct uml_stat buf;
220 int err;
221
222 err = os_stat_file(file, &buf);
223 if(err < 0)
224 return(err);
225
226 if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
227 else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
228 else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
229 else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
230 else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
231 else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
232 else return(OS_TYPE_FILE);
233}
234
235int os_file_mode(char *file, struct openflags *mode_out)
236{
237 int err;
238
239 *mode_out = OPENFLAGS();
240
241 err = os_access(file, OS_ACC_W_OK);
242 if((err < 0) && (err != -EACCES))
243 return(err);
244
245 *mode_out = of_write(*mode_out);
246
247 err = os_access(file, OS_ACC_R_OK);
248 if((err < 0) && (err != -EACCES))
249 return(err);
250
251 *mode_out = of_read(*mode_out);
252
253 return(0);
254}
255
256int os_open_file(char *file, struct openflags flags, int mode)
257{
258 int fd, f = 0;
259
260 if(flags.r && flags.w) f = O_RDWR;
261 else if(flags.r) f = O_RDONLY;
262 else if(flags.w) f = O_WRONLY;
263 else f = 0;
264
265 if(flags.s) f |= O_SYNC;
266 if(flags.c) f |= O_CREAT;
267 if(flags.t) f |= O_TRUNC;
268 if(flags.e) f |= O_EXCL;
269
270 fd = open64(file, f, mode);
271 if(fd < 0)
272 return(-errno);
273
274 if(flags.cl && fcntl(fd, F_SETFD, 1)){
275 os_close_file(fd);
276 return(-errno);
277 }
278
279 return(fd);
280}
281
282int os_connect_socket(char *name)
283{
284 struct sockaddr_un sock;
285 int fd, err;
286
287 sock.sun_family = AF_UNIX;
288 snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
289
290 fd = socket(AF_UNIX, SOCK_STREAM, 0);
291 if(fd < 0)
292 return(fd);
293
294 err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
295 if(err)
296 return(-errno);
297
298 return(fd);
299}
300
301void os_close_file(int fd)
302{
303 close(fd);
304}
305
306int os_seek_file(int fd, __u64 offset)
307{
308 __u64 actual;
309
310 actual = lseek64(fd, offset, SEEK_SET);
311 if(actual != offset)
312 return(-errno);
313 return(0);
314}
315
316static int fault_buffer(void *start, int len,
317 int (*copy_proc)(void *addr, void *buf, int len))
318{
319 int page = getpagesize(), i;
320 char c;
321
322 for(i = 0; i < len; i += page){
323 if((*copy_proc)(start + i, &c, sizeof(c)))
324 return(-EFAULT);
325 }
326 if((len % page) != 0){
327 if((*copy_proc)(start + len - 1, &c, sizeof(c)))
328 return(-EFAULT);
329 }
330 return(0);
331}
332
333static int file_io(int fd, void *buf, int len,
334 int (*io_proc)(int fd, void *buf, int len),
335 int (*copy_user_proc)(void *addr, void *buf, int len))
336{
337 int n, err;
338
339 do {
340 n = (*io_proc)(fd, buf, len);
341 if((n < 0) && (errno == EFAULT)){
342 err = fault_buffer(buf, len, copy_user_proc);
343 if(err)
344 return(err);
345 n = (*io_proc)(fd, buf, len);
346 }
347 } while((n < 0) && (errno == EINTR));
348
349 if(n < 0)
350 return(-errno);
351 return(n);
352}
353
354int os_read_file(int fd, void *buf, int len)
355{
356 return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
357 copy_from_user_proc));
358}
359
360int os_write_file(int fd, const void *buf, int len)
361{
362 return(file_io(fd, (void *) buf, len,
363 (int (*)(int, void *, int)) write, copy_to_user_proc));
364}
365
366int os_file_size(char *file, long long *size_out)
367{
368 struct uml_stat buf;
369 int err;
370
371 err = os_stat_file(file, &buf);
372 if(err < 0){
373 printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
374 return(err);
375 }
376
377 if(S_ISBLK(buf.ust_mode)){
378 int fd, blocks;
379
380 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
381 if(fd < 0){
382 printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
383 return(fd);
384 }
385 if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
386 printk("Couldn't get the block size of \"%s\", "
387 "errno = %d\n", file, errno);
388 err = -errno;
389 os_close_file(fd);
390 return(err);
391 }
392 *size_out = ((long long) blocks) * 512;
393 os_close_file(fd);
394 return(0);
395 }
396 *size_out = buf.ust_size;
397 return(0);
398}
399
400int os_file_modtime(char *file, unsigned long *modtime)
401{
402 struct uml_stat buf;
403 int err;
404
405 err = os_stat_file(file, &buf);
406 if(err < 0){
407 printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
408 return(err);
409 }
410
411 *modtime = buf.ust_mtime;
412 return(0);
413}
414
415int os_get_exec_close(int fd, int* close_on_exec)
416{
417 int ret;
418
419 do {
420 ret = fcntl(fd, F_GETFD);
421 } while((ret < 0) && (errno == EINTR)) ;
422
423 if(ret < 0)
424 return(-errno);
425
426 *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
427 return(ret);
428}
429
430int os_set_exec_close(int fd, int close_on_exec)
431{
432 int flag, err;
433
434 if(close_on_exec) flag = FD_CLOEXEC;
435 else flag = 0;
436
437 do {
438 err = fcntl(fd, F_SETFD, flag);
439 } while((err < 0) && (errno == EINTR)) ;
440
441 if(err < 0)
442 return(-errno);
443 return(err);
444}
445
446int os_pipe(int *fds, int stream, int close_on_exec)
447{
448 int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
449
450 err = socketpair(AF_UNIX, type, 0, fds);
451 if(err < 0)
452 return(-errno);
453
454 if(!close_on_exec)
455 return(0);
456
457 err = os_set_exec_close(fds[0], 1);
458 if(err < 0)
459 goto error;
460
461 err = os_set_exec_close(fds[1], 1);
462 if(err < 0)
463 goto error;
464
465 return(0);
466
467 error:
468 printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
469 os_close_file(fds[1]);
470 os_close_file(fds[0]);
471 return(err);
472}
473
474int os_set_fd_async(int fd, int owner)
475{
476 /* XXX This should do F_GETFL first */
477 if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
478 printk("os_set_fd_async : failed to set O_ASYNC and "
479 "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
480 return(-errno);
481 }
482#ifdef notdef
483 if(fcntl(fd, F_SETFD, 1) < 0){
484 printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
485 "errno = %d\n", errno);
486 }
487#endif
488
489 if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
490 (fcntl(fd, F_SETOWN, owner) < 0)){
491 printk("os_set_fd_async : Failed to fcntl F_SETOWN "
492 "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
493 owner, errno);
494 return(-errno);
495 }
496
497 return(0);
498}
499
500int os_clear_fd_async(int fd)
501{
502 int flags = fcntl(fd, F_GETFL);
503
504 flags &= ~(O_ASYNC | O_NONBLOCK);
505 if(fcntl(fd, F_SETFL, flags) < 0)
506 return(-errno);
507 return(0);
508}
509
510int os_set_fd_block(int fd, int blocking)
511{
512 int flags;
513
514 flags = fcntl(fd, F_GETFL);
515
516 if(blocking) flags &= ~O_NONBLOCK;
517 else flags |= O_NONBLOCK;
518
519 if(fcntl(fd, F_SETFL, flags) < 0){
520 printk("Failed to change blocking on fd # %d, errno = %d\n",
521 fd, errno);
522 return(-errno);
523 }
524 return(0);
525}
526
527int os_accept_connection(int fd)
528{
529 int new;
530
531 new = accept(fd, NULL, 0);
532 if(new < 0)
533 return(-errno);
534 return(new);
535}
536
537#ifndef SHUT_RD
538#define SHUT_RD 0
539#endif
540
541#ifndef SHUT_WR
542#define SHUT_WR 1
543#endif
544
545#ifndef SHUT_RDWR
546#define SHUT_RDWR 2
547#endif
548
549int os_shutdown_socket(int fd, int r, int w)
550{
551 int what, err;
552
553 if(r && w) what = SHUT_RDWR;
554 else if(r) what = SHUT_RD;
555 else if(w) what = SHUT_WR;
556 else {
557 printk("os_shutdown_socket : neither r or w was set\n");
558 return(-EINVAL);
559 }
560 err = shutdown(fd, what);
561 if(err < 0)
562 return(-errno);
563 return(0);
564}
565
566int os_rcv_fd(int fd, int *helper_pid_out)
567{
568 int new, n;
569 char buf[CMSG_SPACE(sizeof(new))];
570 struct msghdr msg;
571 struct cmsghdr *cmsg;
572 struct iovec iov;
573
574 msg.msg_name = NULL;
575 msg.msg_namelen = 0;
576 iov = ((struct iovec) { .iov_base = helper_pid_out,
577 .iov_len = sizeof(*helper_pid_out) });
578 msg.msg_iov = &iov;
579 msg.msg_iovlen = 1;
580 msg.msg_control = buf;
581 msg.msg_controllen = sizeof(buf);
582 msg.msg_flags = 0;
583
584 n = recvmsg(fd, &msg, 0);
585 if(n < 0)
586 return(-errno);
587
588 else if(n != sizeof(iov.iov_len))
589 *helper_pid_out = -1;
590
591 cmsg = CMSG_FIRSTHDR(&msg);
592 if(cmsg == NULL){
593 printk("rcv_fd didn't receive anything, error = %d\n", errno);
594 return(-1);
595 }
596 if((cmsg->cmsg_level != SOL_SOCKET) ||
597 (cmsg->cmsg_type != SCM_RIGHTS)){
598 printk("rcv_fd didn't receive a descriptor\n");
599 return(-1);
600 }
601
602 new = ((int *) CMSG_DATA(cmsg))[0];
603 return(new);
604}
605
606int os_create_unix_socket(char *file, int len, int close_on_exec)
607{
608 struct sockaddr_un addr;
609 int sock, err;
610
611 sock = socket(PF_UNIX, SOCK_DGRAM, 0);
612 if (sock < 0){
613 printk("create_unix_socket - socket failed, errno = %d\n",
614 errno);
615 return(-errno);
616 }
617
618 if(close_on_exec) {
619 err = os_set_exec_close(sock, 1);
620 if(err < 0)
621 printk("create_unix_socket : close_on_exec failed, "
622 "err = %d", -err);
623 }
624
625 addr.sun_family = AF_UNIX;
626
627 /* XXX Be more careful about overflow */
628 snprintf(addr.sun_path, len, "%s", file);
629
630 err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
631 if (err < 0){
632 printk("create_listening_socket at '%s' - bind failed, "
633 "errno = %d\n", file, errno);
634 return(-errno);
635 }
636
637 return(sock);
638}
639
640void os_flush_stdout(void)
641{
642 fflush(stdout);
643}
644
645int os_lock_file(int fd, int excl)
646{
647 int type = excl ? F_WRLCK : F_RDLCK;
648 struct flock lock = ((struct flock) { .l_type = type,
649 .l_whence = SEEK_SET,
650 .l_start = 0,
651 .l_len = 0 } );
652 int err, save;
653
654 err = fcntl(fd, F_SETLK, &lock);
655 if(!err)
656 goto out;
657
658 save = -errno;
659 err = fcntl(fd, F_GETLK, &lock);
660 if(err){
661 err = -errno;
662 goto out;
663 }
664
665 printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
666 err = save;
667 out:
668 return(err);
669}
670
671/*
672 * Overrides for Emacs so that we follow Linus's tabbing style.
673 * Emacs will notice this stuff at the end of the file and automatically
674 * adjust the settings for this buffer only. This must remain at the end
675 * of the file.
676 * ---------------------------------------------------------------------------
677 * Local variables:
678 * c-file-style: "linux"
679 * End:
680 */
diff --git a/arch/um/os-Linux/include/file.h b/arch/um/os-Linux/include/file.h
new file mode 100644
index 000000000000..d82711efacfa
--- /dev/null
+++ b/arch/um/os-Linux/include/file.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#ifndef __OS_FILE_H__
7#define __OS_FILE_H__
8
9#define DEV_NULL "/dev/null"
10
11#endif
12
13/*
14 * Overrides for Emacs so that we follow Linus's tabbing style.
15 * Emacs will notice this stuff at the end of the file and automatically
16 * adjust the settings for this buffer only. This must remain at the end
17 * of the file.
18 * ---------------------------------------------------------------------------
19 * Local variables:
20 * c-file-style: "linux"
21 * End:
22 */
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
new file mode 100644
index 000000000000..ba9ca1cc790a
--- /dev/null
+++ b/arch/um/os-Linux/process.c
@@ -0,0 +1,171 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
3 * Licensed under the GPL
4 */
5
6#include <unistd.h>
7#include <stdio.h>
8#include <errno.h>
9#include <signal.h>
10#include <linux/unistd.h>
11#include <sys/mman.h>
12#include <sys/wait.h>
13#include "ptrace_user.h"
14#include "os.h"
15#include "user.h"
16#include "user_util.h"
17
18#define ARBITRARY_ADDR -1
19#define FAILURE_PID -1
20
21#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
22#define COMM_SCANF "%*[^)])"
23
24unsigned long os_process_pc(int pid)
25{
26 char proc_stat[STAT_PATH_LEN], buf[256];
27 unsigned long pc;
28 int fd, err;
29
30 sprintf(proc_stat, "/proc/%d/stat", pid);
31 fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
32 if(fd < 0){
33 printk("os_process_pc - couldn't open '%s', err = %d\n",
34 proc_stat, -fd);
35 return(ARBITRARY_ADDR);
36 }
37 err = os_read_file(fd, buf, sizeof(buf));
38 if(err < 0){
39 printk("os_process_pc - couldn't read '%s', err = %d\n",
40 proc_stat, -err);
41 os_close_file(fd);
42 return(ARBITRARY_ADDR);
43 }
44 os_close_file(fd);
45 pc = ARBITRARY_ADDR;
46 if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
47 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
48 "%*d %*d %*d %*d %*d %lu", &pc) != 1){
49 printk("os_process_pc - couldn't find pc in '%s'\n", buf);
50 }
51 return(pc);
52}
53
54int os_process_parent(int pid)
55{
56 char stat[STAT_PATH_LEN];
57 char data[256];
58 int parent, n, fd;
59
60 if(pid == -1) return(-1);
61
62 snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
63 fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
64 if(fd < 0){
65 printk("Couldn't open '%s', err = %d\n", stat, -fd);
66 return(FAILURE_PID);
67 }
68
69 n = os_read_file(fd, data, sizeof(data));
70 os_close_file(fd);
71
72 if(n < 0){
73 printk("Couldn't read '%s', err = %d\n", stat, -n);
74 return(FAILURE_PID);
75 }
76
77 parent = FAILURE_PID;
78 n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
79 if(n != 1)
80 printk("Failed to scan '%s'\n", data);
81
82 return(parent);
83}
84
85void os_stop_process(int pid)
86{
87 kill(pid, SIGSTOP);
88}
89
90void os_kill_process(int pid, int reap_child)
91{
92 kill(pid, SIGKILL);
93 if(reap_child)
94 CATCH_EINTR(waitpid(pid, NULL, 0));
95
96}
97
98/* Kill off a ptraced child by all means available. kill it normally first,
99 * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from
100 * which it can't exit directly.
101 */
102
103void os_kill_ptraced_process(int pid, int reap_child)
104{
105 kill(pid, SIGKILL);
106 ptrace(PTRACE_KILL, pid);
107 ptrace(PTRACE_CONT, pid);
108 if(reap_child)
109 CATCH_EINTR(waitpid(pid, NULL, 0));
110}
111
112void os_usr1_process(int pid)
113{
114 kill(pid, SIGUSR1);
115}
116
117/*Don't use the glibc version, which caches the result in TLS. It misses some
118 * syscalls, and also breaks with clone(), which does not unshare the TLS.*/
119inline _syscall0(pid_t, getpid)
120
121int os_getpid(void)
122{
123 return(getpid());
124}
125
126int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
127 int r, int w, int x)
128{
129 void *loc;
130 int prot;
131
132 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
133 (x ? PROT_EXEC : 0);
134
135 loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
136 fd, off);
137 if(loc == MAP_FAILED)
138 return(-errno);
139 return(0);
140}
141
142int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
143{
144 int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
145 (x ? PROT_EXEC : 0));
146
147 if(mprotect(addr, len, prot) < 0)
148 return(-errno);
149 return(0);
150}
151
152int os_unmap_memory(void *addr, int len)
153{
154 int err;
155
156 err = munmap(addr, len);
157 if(err < 0)
158 return(-errno);
159 return(0);
160}
161
162/*
163 * Overrides for Emacs so that we follow Linus's tabbing style.
164 * Emacs will notice this stuff at the end of the file and automatically
165 * adjust the settings for this buffer only. This must remain at the end
166 * of the file.
167 * ---------------------------------------------------------------------------
168 * Local variables:
169 * c-file-style: "linux"
170 * End:
171 */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
new file mode 100644
index 000000000000..7eac1baf5975
--- /dev/null
+++ b/arch/um/os-Linux/signal.c
@@ -0,0 +1,48 @@
1/*
2 * Copyright (C) 2004 PathScale, Inc
3 * Licensed under the GPL
4 */
5
6#include <signal.h>
7#include "time_user.h"
8#include "mode.h"
9#include "sysdep/signal.h"
10
11void sig_handler(int sig)
12{
13 struct sigcontext *sc;
14
15 ARCH_GET_SIGCONTEXT(sc, sig);
16 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
17 sig, sc);
18}
19
20extern int timer_irq_inited;
21
22void alarm_handler(int sig)
23{
24 struct sigcontext *sc;
25
26 ARCH_GET_SIGCONTEXT(sc, sig);
27 if(!timer_irq_inited) return;
28
29 if(sig == SIGALRM)
30 switch_timers(0);
31
32 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
33 sig, sc);
34
35 if(sig == SIGALRM)
36 switch_timers(1);
37}
38
39/*
40 * Overrides for Emacs so that we follow Linus's tabbing style.
41 * Emacs will notice this stuff at the end of the file and automatically
42 * adjust the settings for this buffer only. This must remain at the end
43 * of the file.
44 * ---------------------------------------------------------------------------
45 * Local variables:
46 * c-file-style: "linux"
47 * End:
48 */
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
new file mode 100644
index 000000000000..340ef26f5944
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -0,0 +1,10 @@
1#
2# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3# Licensed under the GPL
4#
5
6obj-$(CONFIG_MODE_SKAS) = registers.o
7
8USER_OBJS := $(obj-y)
9
10include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
new file mode 100644
index 000000000000..148645b14480
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -0,0 +1,132 @@
1/*
2 * Copyright (C) 2004 PathScale, Inc
3 * Licensed under the GPL
4 */
5
6#include <errno.h>
7#include <string.h>
8#include "sysdep/ptrace_user.h"
9#include "sysdep/ptrace.h"
10#include "uml-config.h"
11#include "skas_ptregs.h"
12#include "registers.h"
13#include "user.h"
14
15/* These are set once at boot time and not changed thereafter */
16
17static unsigned long exec_regs[HOST_FRAME_SIZE];
18static unsigned long exec_fp_regs[HOST_FP_SIZE];
19static unsigned long exec_fpx_regs[HOST_XFP_SIZE];
20static int have_fpx_regs = 1;
21
22void init_thread_registers(union uml_pt_regs *to)
23{
24 memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs));
25 memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
26 if(have_fpx_regs)
27 memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp));
28}
29
30/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs
31 * to pass in a sufficiently large buffer
32 */
33int save_fp_registers(int pid, unsigned long *fp_regs)
34{
35 if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
36 return(-errno);
37 return(0);
38}
39
40int restore_fp_registers(int pid, unsigned long *fp_regs)
41{
42 if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
43 return(-errno);
44 return(0);
45}
46
47static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
48 int fp_op, unsigned long *fp_regs)
49{
50 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
51 return(-errno);
52
53 if(ptrace(fp_op, pid, 0, fp_regs) < 0)
54 return(-errno);
55
56 return(0);
57}
58
59void save_registers(int pid, union uml_pt_regs *regs)
60{
61 unsigned long *fp_regs;
62 int err, fp_op;
63
64 if(have_fpx_regs){
65 fp_op = PTRACE_GETFPXREGS;
66 fp_regs = regs->skas.xfp;
67 }
68 else {
69 fp_op = PTRACE_GETFPREGS;
70 fp_regs = regs->skas.fp;
71 }
72
73 err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs);
74 if(err)
75 panic("save_registers - saving registers failed, errno = %d\n",
76 -err);
77}
78
79void restore_registers(int pid, union uml_pt_regs *regs)
80{
81 unsigned long *fp_regs;
82 int err, fp_op;
83
84 if(have_fpx_regs){
85 fp_op = PTRACE_SETFPXREGS;
86 fp_regs = regs->skas.xfp;
87 }
88 else {
89 fp_op = PTRACE_SETFPREGS;
90 fp_regs = regs->skas.fp;
91 }
92
93 err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs);
94 if(err)
95 panic("restore_registers - saving registers failed, "
96 "errno = %d\n", -err);
97}
98
99void init_registers(int pid)
100{
101 int err;
102
103 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
104 if(err)
105 panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
106 err);
107
108 err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
109 if(!err)
110 return;
111
112 have_fpx_regs = 0;
113 if(err != EIO)
114 panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
115 err);
116
117 err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
118 if(err)
119 panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
120 err);
121}
122
123/*
124 * Overrides for Emacs so that we follow Linus's tabbing style.
125 * Emacs will notice this stuff at the end of the file and automatically
126 * adjust the settings for this buffer only. This must remain at the end
127 * of the file.
128 * ---------------------------------------------------------------------------
129 * Local variables:
130 * c-file-style: "linux"
131 * End:
132 */
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
new file mode 100644
index 000000000000..340ef26f5944
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -0,0 +1,10 @@
1#
2# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3# Licensed under the GPL
4#
5
6obj-$(CONFIG_MODE_SKAS) = registers.o
7
8USER_OBJS := $(obj-y)
9
10include arch/um/scripts/Makefile.rules
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
new file mode 100644
index 000000000000..6286c974bbeb
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -0,0 +1,81 @@
1/*
2 * Copyright (C) 2004 PathScale, Inc
3 * Licensed under the GPL
4 */
5
6#include <errno.h>
7#include <string.h>
8#include "ptrace_user.h"
9#include "uml-config.h"
10#include "skas_ptregs.h"
11#include "registers.h"
12#include "user.h"
13
14/* These are set once at boot time and not changed thereafter */
15
16static unsigned long exec_regs[HOST_FRAME_SIZE];
17static unsigned long exec_fp_regs[HOST_FP_SIZE];
18
19void init_thread_registers(union uml_pt_regs *to)
20{
21 memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs));
22 memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
23}
24
25static int move_registers(int pid, int int_op, int fp_op,
26 union uml_pt_regs *regs)
27{
28 if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
29 return(-errno);
30
31 if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0)
32 return(-errno);
33
34 return(0);
35}
36
37void save_registers(int pid, union uml_pt_regs *regs)
38{
39 int err;
40
41 err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs);
42 if(err)
43 panic("save_registers - saving registers failed, errno = %d\n",
44 -err);
45}
46
47void restore_registers(int pid, union uml_pt_regs *regs)
48{
49 int err;
50
51 err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs);
52 if(err)
53 panic("restore_registers - saving registers failed, "
54 "errno = %d\n", -err);
55}
56
57void init_registers(int pid)
58{
59 int err;
60
61 err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
62 if(err)
63 panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
64 err);
65
66 err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
67 if(err)
68 panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
69 err);
70}
71
72/*
73 * Overrides for Emacs so that we follow Linus's tabbing style.
74 * Emacs will notice this stuff at the end of the file and automatically
75 * adjust the settings for this buffer only. This must remain at the end
76 * of the file.
77 * ---------------------------------------------------------------------------
78 * Local variables:
79 * c-file-style: "linux"
80 * End:
81 */
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
new file mode 100644
index 000000000000..cf30a39bc484
--- /dev/null
+++ b/arch/um/os-Linux/time.c
@@ -0,0 +1,21 @@
1#include <stdlib.h>
2#include <sys/time.h>
3
4unsigned long long os_usecs(void)
5{
6 struct timeval tv;
7
8 gettimeofday(&tv, NULL);
9 return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec);
10}
11
12/*
13 * Overrides for Emacs so that we follow Linus's tabbing style.
14 * Emacs will notice this stuff at the end of the file and automatically
15 * adjust the settings for this buffer only. This must remain at the end
16 * of the file.
17 * ---------------------------------------------------------------------------
18 * Local variables:
19 * c-file-style: "linux"
20 * End:
21 */
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
new file mode 100644
index 000000000000..4cfdd18ea1ef
--- /dev/null
+++ b/arch/um/os-Linux/tty.c
@@ -0,0 +1,61 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <errno.h>
8#include "os.h"
9#include "user.h"
10#include "kern_util.h"
11
12struct grantpt_info {
13 int fd;
14 int res;
15 int err;
16};
17
18static void grantpt_cb(void *arg)
19{
20 struct grantpt_info *info = arg;
21
22 info->res = grantpt(info->fd);
23 info->err = errno;
24}
25
26int get_pty(void)
27{
28 struct grantpt_info info;
29 int fd;
30
31 fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
32 if(fd < 0){
33 printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
34 return(fd);
35 }
36
37 info.fd = fd;
38 initial_thread_cb(grantpt_cb, &info);
39
40 if(info.res < 0){
41 printk("get_pty : Couldn't grant pty - errno = %d\n",
42 -info.err);
43 return(-1);
44 }
45 if(unlockpt(fd) < 0){
46 printk("get_pty : Couldn't unlock pty - errno = %d\n", errno);
47 return(-1);
48 }
49 return(fd);
50}
51
52/*
53 * Overrides for Emacs so that we follow Linus's tabbing style.
54 * Emacs will notice this stuff at the end of the file and automatically
55 * adjust the settings for this buffer only. This must remain at the end
56 * of the file.
57 * ---------------------------------------------------------------------------
58 * Local variables:
59 * c-file-style: "linux"
60 * End:
61 */
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
new file mode 100644
index 000000000000..75d7af9ae1d2
--- /dev/null
+++ b/arch/um/os-Linux/user_syms.c
@@ -0,0 +1,95 @@
1#include "linux/types.h"
2#include "linux/module.h"
3
4/* Some of this are builtin function (some are not but could in the future),
5 * so I *must* declare good prototypes for them and then EXPORT them.
6 * The kernel code uses the macro defined by include/linux/string.h,
7 * so I undef macros; the userspace code does not include that and I
8 * add an EXPORT for the glibc one.*/
9
10#undef strlen
11#undef strstr
12#undef memcpy
13#undef memset
14
15extern size_t strlen(const char *);
16extern void *memcpy(void *, const void *, size_t);
17extern void *memmove(void *, const void *, size_t);
18extern void *memset(void *, int, size_t);
19extern int printf(const char *, ...);
20
21EXPORT_SYMBOL(strlen);
22EXPORT_SYMBOL(memcpy);
23EXPORT_SYMBOL(memmove);
24EXPORT_SYMBOL(memset);
25EXPORT_SYMBOL(printf);
26
27EXPORT_SYMBOL(strstr);
28
29/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
30 * However, the modules will use the CRC defined *here*, no matter if it is
31 * good; so the versions of these symbols will always match
32 */
33#define EXPORT_SYMBOL_PROTO(sym) \
34 int sym(void); \
35 EXPORT_SYMBOL(sym);
36
37#ifdef SUBARCH_i386
38EXPORT_SYMBOL(vsyscall_ehdr);
39EXPORT_SYMBOL(vsyscall_end);
40#endif
41
42EXPORT_SYMBOL_PROTO(__errno_location);
43
44EXPORT_SYMBOL_PROTO(access);
45EXPORT_SYMBOL_PROTO(open);
46EXPORT_SYMBOL_PROTO(open64);
47EXPORT_SYMBOL_PROTO(close);
48EXPORT_SYMBOL_PROTO(read);
49EXPORT_SYMBOL_PROTO(write);
50EXPORT_SYMBOL_PROTO(dup2);
51EXPORT_SYMBOL_PROTO(__xstat);
52EXPORT_SYMBOL_PROTO(__lxstat);
53EXPORT_SYMBOL_PROTO(__lxstat64);
54EXPORT_SYMBOL_PROTO(lseek);
55EXPORT_SYMBOL_PROTO(lseek64);
56EXPORT_SYMBOL_PROTO(chown);
57EXPORT_SYMBOL_PROTO(truncate);
58EXPORT_SYMBOL_PROTO(utime);
59EXPORT_SYMBOL_PROTO(chmod);
60EXPORT_SYMBOL_PROTO(rename);
61EXPORT_SYMBOL_PROTO(__xmknod);
62
63EXPORT_SYMBOL_PROTO(symlink);
64EXPORT_SYMBOL_PROTO(link);
65EXPORT_SYMBOL_PROTO(unlink);
66EXPORT_SYMBOL_PROTO(readlink);
67
68EXPORT_SYMBOL_PROTO(mkdir);
69EXPORT_SYMBOL_PROTO(rmdir);
70EXPORT_SYMBOL_PROTO(opendir);
71EXPORT_SYMBOL_PROTO(readdir);
72EXPORT_SYMBOL_PROTO(closedir);
73EXPORT_SYMBOL_PROTO(seekdir);
74EXPORT_SYMBOL_PROTO(telldir);
75
76EXPORT_SYMBOL_PROTO(ioctl);
77
78EXPORT_SYMBOL_PROTO(pread64);
79EXPORT_SYMBOL_PROTO(pwrite64);
80
81EXPORT_SYMBOL_PROTO(statfs);
82EXPORT_SYMBOL_PROTO(statfs64);
83
84EXPORT_SYMBOL_PROTO(getuid);
85
86/*
87 * Overrides for Emacs so that we follow Linus's tabbing style.
88 * Emacs will notice this stuff at the end of the file and automatically
89 * adjust the settings for this buffer only. This must remain at the end
90 * of the file.
91 * ---------------------------------------------------------------------------
92 * Local variables:
93 * c-file-style: "linux"
94 * End:
95 */
diff --git a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile
new file mode 100644
index 000000000000..fb00ddf969bd
--- /dev/null
+++ b/arch/um/os-Linux/util/Makefile
@@ -0,0 +1,4 @@
1hostprogs-y := mk_user_constants
2always := $(hostprogs-y)
3
4mk_user_constants-objs := mk_user_constants.o
diff --git a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c
new file mode 100644
index 000000000000..0933518aa8bd
--- /dev/null
+++ b/arch/um/os-Linux/util/mk_user_constants.c
@@ -0,0 +1,29 @@
1#include <stdio.h>
2#include <asm/types.h>
3/* For some reason, x86_64 nowhere defines u64 and u32, even though they're
4 * used throughout the headers.
5 */
6typedef __u64 u64;
7typedef __u32 u32;
8#include <asm/user.h>
9
10int main(int argc, char **argv)
11{
12 printf("/*\n");
13 printf(" * Generated by mk_user_constants\n");
14 printf(" */\n");
15 printf("\n");
16 printf("#ifndef __UM_USER_CONSTANTS_H\n");
17 printf("#define __UM_USER_CONSTANTS_H\n");
18 printf("\n");
19 /* I'd like to use FRAME_SIZE from ptrace.h here, but that's wrong on
20 * x86_64 (216 vs 168 bytes). user_regs_struct is the correct size on
21 * both x86_64 and i386.
22 */
23 printf("#define UM_FRAME_SIZE %d\n", (int) sizeof(struct user_regs_struct));
24
25 printf("\n");
26 printf("#endif\n");
27
28 return(0);
29}