diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /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/Makefile | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/Makefile | 13 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/etap.h | 27 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/ethertap_kern.c | 119 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/ethertap_user.c | 240 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap.h | 32 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_kern.c | 104 | ||||
-rw-r--r-- | arch/um/os-Linux/drivers/tuntap_user.c | 225 | ||||
-rw-r--r-- | arch/um/os-Linux/elf_aux.c | 66 | ||||
-rw-r--r-- | arch/um/os-Linux/file.c | 680 | ||||
-rw-r--r-- | arch/um/os-Linux/include/file.h | 22 | ||||
-rw-r--r-- | arch/um/os-Linux/process.c | 171 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 48 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/Makefile | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 132 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/Makefile | 10 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 81 | ||||
-rw-r--r-- | arch/um/os-Linux/time.c | 21 | ||||
-rw-r--r-- | arch/um/os-Linux/tty.c | 61 | ||||
-rw-r--r-- | arch/um/os-Linux/user_syms.c | 95 | ||||
-rw-r--r-- | arch/um/os-Linux/util/Makefile | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/util/mk_user_constants.c | 29 |
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 00000000000..4ddf540284c --- /dev/null +++ b/arch/um/os-Linux/Makefile @@ -0,0 +1,13 @@ +# +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +obj-y = elf_aux.o file.o process.o signal.o time.o tty.o user_syms.o drivers/ \ + sys-$(SUBARCH)/ + +USER_OBJS := elf_aux.o file.o process.o signal.o time.o tty.o + +CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) + +include 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 00000000000..6c546dc9222 --- /dev/null +++ b/arch/um/os-Linux/drivers/Makefile @@ -0,0 +1,13 @@ +# +# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +ethertap-objs := ethertap_kern.o ethertap_user.o +tuntap-objs := tuntap_kern.o tuntap_user.o + +obj-y = +obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap.o +obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o + +include 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 00000000000..b84f6c4740f --- /dev/null +++ b/arch/um/os-Linux/drivers/etap.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "net_user.h" + +struct ethertap_data { + char *dev_name; + char *gate_addr; + int data_fd; + int control_fd; + void *dev; +}; + +extern struct net_user_info ethertap_user_info; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ 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 00000000000..6ae4b19d9f5 --- /dev/null +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 by various other people who didn't put their name here. + * Licensed under the GPL. + */ + +#include "linux/init.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "net_kern.h" +#include "net_user.h" +#include "etap.h" + +struct ethertap_init { + char *dev_name; + char *gate_addr; +}; + +static void etap_init(struct net_device *dev, void *data) +{ + struct uml_net_private *pri; + struct ethertap_data *epri; + struct ethertap_init *init = data; + + pri = dev->priv; + epri = (struct ethertap_data *) pri->user; + epri->dev_name = init->dev_name; + epri->gate_addr = init->gate_addr; + epri->data_fd = -1; + epri->control_fd = -1; + epri->dev = dev; + + printk("ethertap backend - %s", epri->dev_name); + if (epri->gate_addr != NULL) + printk(", IP = %s", epri->gate_addr); + printk("\n"); +} + +static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) +{ + int len; + + *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); + if(*skb == NULL) return(-ENOMEM); + len = net_recvfrom(fd, (*skb)->mac.raw, + (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); + if(len <= 0) return(len); + skb_pull(*skb, 2); + len -= 2; + return(len); +} + +static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) +{ + if(skb_headroom(*skb) < 2){ + struct sk_buff *skb2; + + skb2 = skb_realloc_headroom(*skb, 2); + dev_kfree_skb(*skb); + if (skb2 == NULL) return(-ENOMEM); + *skb = skb2; + } + skb_push(*skb, 2); + return(net_send(fd, (*skb)->data, (*skb)->len)); +} + +struct net_kern_info ethertap_kern_info = { + .init = etap_init, + .protocol = eth_protocol, + .read = etap_read, + .write = etap_write, +}; + +int ethertap_setup(char *str, char **mac_out, void *data) +{ + struct ethertap_init *init = data; + + *init = ((struct ethertap_init) + { .dev_name = NULL, + .gate_addr = NULL }); + if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, + &init->gate_addr)) + return(0); + if(init->dev_name == NULL){ + printk("ethertap_setup : Missing tap device name\n"); + return(0); + } + + return(1); +} + +static struct transport ethertap_transport = { + .list = LIST_HEAD_INIT(ethertap_transport.list), + .name = "ethertap", + .setup = ethertap_setup, + .user = ðertap_user_info, + .kern = ðertap_kern_info, + .private_size = sizeof(struct ethertap_data), +}; + +static int register_ethertap(void) +{ + register_transport(ðertap_transport); + return(1); +} + +__initcall(register_ethertap); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ 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 00000000000..cd4d6544da7 --- /dev/null +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 by various other people who didn't put their name here. + * Licensed under the GPL. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stddef.h> +#include <stdlib.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <sys/un.h> +#include <net/if.h> +#include "user.h" +#include "kern_util.h" +#include "user_util.h" +#include "net_user.h" +#include "etap.h" +#include "helper.h" +#include "os.h" + +#define MAX_PACKET ETH_MAX_PACKET + +void etap_user_init(void *data, void *dev) +{ + struct ethertap_data *pri = data; + + pri->dev = dev; +} + +struct addr_change { + enum { ADD_ADDR, DEL_ADDR } what; + unsigned char addr[4]; + unsigned char netmask[4]; +}; + +static void etap_change(int op, unsigned char *addr, unsigned char *netmask, + int fd) +{ + struct addr_change change; + void *output; + int n; + + change.what = op; + memcpy(change.addr, addr, sizeof(change.addr)); + memcpy(change.netmask, netmask, sizeof(change.netmask)); + n = os_write_file(fd, &change, sizeof(change)); + if(n != sizeof(change)) + printk("etap_change - request failed, err = %d\n", -n); + output = um_kmalloc(page_size()); + if(output == NULL) + printk("etap_change : Failed to allocate output buffer\n"); + read_output(fd, output, page_size()); + if(output != NULL){ + printk("%s", output); + kfree(output); + } +} + +static void etap_open_addr(unsigned char *addr, unsigned char *netmask, + void *arg) +{ + etap_change(ADD_ADDR, addr, netmask, *((int *) arg)); +} + +static void etap_close_addr(unsigned char *addr, unsigned char *netmask, + void *arg) +{ + etap_change(DEL_ADDR, addr, netmask, *((int *) arg)); +} + +struct etap_pre_exec_data { + int control_remote; + int control_me; + int data_me; +}; + +static void etap_pre_exec(void *arg) +{ + struct etap_pre_exec_data *data = arg; + + dup2(data->control_remote, 1); + os_close_file(data->data_me); + os_close_file(data->control_me); +} + +static int etap_tramp(char *dev, char *gate, int control_me, + int control_remote, int data_me, int data_remote) +{ + struct etap_pre_exec_data pe_data; + int pid, status, err, n; + char version_buf[sizeof("nnnnn\0")]; + char data_fd_buf[sizeof("nnnnnn\0")]; + char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; + char *setup_args[] = { "uml_net", version_buf, "ethertap", dev, + data_fd_buf, gate_buf, NULL }; + char *nosetup_args[] = { "uml_net", version_buf, "ethertap", + dev, data_fd_buf, NULL }; + char **args, c; + + sprintf(data_fd_buf, "%d", data_remote); + sprintf(version_buf, "%d", UML_NET_VERSION); + if(gate != NULL){ + strcpy(gate_buf, gate); + args = setup_args; + } + else args = nosetup_args; + + err = 0; + pe_data.control_remote = control_remote; + pe_data.control_me = control_me; + pe_data.data_me = data_me; + pid = run_helper(etap_pre_exec, &pe_data, args, NULL); + + if(pid < 0) err = pid; + os_close_file(data_remote); + os_close_file(control_remote); + n = os_read_file(control_me, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("etap_tramp : read of status failed, err = %d\n", -n); + return(-EINVAL); + } + if(c != 1){ + printk("etap_tramp : uml_net failed\n"); + err = -EINVAL; + CATCH_EINTR(n = waitpid(pid, &status, 0)); + if(n < 0) + err = -errno; + else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) + printk("uml_net didn't exit with status 1\n"); + } + return(err); +} + +static int etap_open(void *data) +{ + struct ethertap_data *pri = data; + char *output; + int data_fds[2], control_fds[2], err, output_len; + + err = tap_open_common(pri->dev, pri->gate_addr); + if(err) return(err); + + err = os_pipe(data_fds, 0, 0); + if(err < 0){ + printk("data os_pipe failed - err = %d\n", -err); + return(err); + } + + err = os_pipe(control_fds, 1, 0); + if(err < 0){ + printk("control os_pipe failed - err = %d\n", -err); + return(err); + } + + err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], + control_fds[1], data_fds[0], data_fds[1]); + output_len = page_size(); + output = um_kmalloc(output_len); + read_output(control_fds[0], output, output_len); + + if(output == NULL) + printk("etap_open : failed to allocate output buffer\n"); + else { + printk("%s", output); + kfree(output); + } + + if(err < 0){ + printk("etap_tramp failed - err = %d\n", -err); + return(err); + } + + pri->data_fd = data_fds[0]; + pri->control_fd = control_fds[0]; + iter_addresses(pri->dev, etap_open_addr, &pri->control_fd); + return(data_fds[0]); +} + +static void etap_close(int fd, void *data) +{ + struct ethertap_data *pri = data; + + iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); + os_close_file(fd); + os_shutdown_socket(pri->data_fd, 1, 1); + os_close_file(pri->data_fd); + pri->data_fd = -1; + os_close_file(pri->control_fd); + pri->control_fd = -1; +} + +static int etap_set_mtu(int mtu, void *data) +{ + return(mtu); +} + +static void etap_add_addr(unsigned char *addr, unsigned char *netmask, + void *data) +{ + struct ethertap_data *pri = data; + + tap_check_ips(pri->gate_addr, addr); + if(pri->control_fd == -1) return; + etap_open_addr(addr, netmask, &pri->control_fd); +} + +static void etap_del_addr(unsigned char *addr, unsigned char *netmask, + void *data) +{ + struct ethertap_data *pri = data; + + if(pri->control_fd == -1) return; + etap_close_addr(addr, netmask, &pri->control_fd); +} + +struct net_user_info ethertap_user_info = { + .init = etap_user_init, + .open = etap_open, + .close = etap_close, + .remove = NULL, + .set_mtu = etap_set_mtu, + .add_address = etap_add_addr, + .delete_address = etap_del_addr, + .max_packet = MAX_PACKET - ETH_HEADER_ETHERTAP +}; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h new file mode 100644 index 00000000000..25d4a286881 --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __UM_TUNTAP_H +#define __UM_TUNTAP_H + +#include "net_user.h" + +struct tuntap_data { + char *dev_name; + int fixed_config; + char *gate_addr; + int fd; + void *dev; +}; + +extern struct net_user_info tuntap_user_info; + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ 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 00000000000..4202b9ebad4 --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "linux/skbuff.h" +#include "linux/init.h" +#include "asm/errno.h" +#include "net_kern.h" +#include "net_user.h" +#include "tuntap.h" + +struct tuntap_init { + char *dev_name; + char *gate_addr; +}; + +static void tuntap_init(struct net_device *dev, void *data) +{ + struct uml_net_private *pri; + struct tuntap_data *tpri; + struct tuntap_init *init = data; + + pri = dev->priv; + tpri = (struct tuntap_data *) pri->user; + tpri->dev_name = init->dev_name; + tpri->fixed_config = (init->dev_name != NULL); + tpri->gate_addr = init->gate_addr; + tpri->fd = -1; + tpri->dev = dev; + + printk("TUN/TAP backend - "); + if (tpri->gate_addr != NULL) + printk("IP = %s", tpri->gate_addr); + printk("\n"); +} + +static int tuntap_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) +{ + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); + if(*skb == NULL) return(-ENOMEM); + return(net_read(fd, (*skb)->mac.raw, + (*skb)->dev->mtu + ETH_HEADER_OTHER)); +} + +static int tuntap_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) +{ + return(net_write(fd, (*skb)->data, (*skb)->len)); +} + +struct net_kern_info tuntap_kern_info = { + .init = tuntap_init, + .protocol = eth_protocol, + .read = tuntap_read, + .write = tuntap_write, +}; + +int tuntap_setup(char *str, char **mac_out, void *data) +{ + struct tuntap_init *init = data; + + *init = ((struct tuntap_init) + { .dev_name = NULL, + .gate_addr = NULL }); + if(tap_setup_common(str, "tuntap", &init->dev_name, mac_out, + &init->gate_addr)) + return(0); + + return(1); +} + +static struct transport tuntap_transport = { + .list = LIST_HEAD_INIT(tuntap_transport.list), + .name = "tuntap", + .setup = tuntap_setup, + .user = &tuntap_user_info, + .kern = &tuntap_kern_info, + .private_size = sizeof(struct tuntap_data), + .setup_size = sizeof(struct tuntap_init), +}; + +static int register_tuntap(void) +{ + register_transport(&tuntap_transport); + return(1); +} + +__initcall(register_tuntap); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ 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 00000000000..4b83c6c3f48 --- /dev/null +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <linux/if_tun.h> +#include "net_user.h" +#include "tuntap.h" +#include "kern_util.h" +#include "user_util.h" +#include "user.h" +#include "helper.h" +#include "os.h" + +#define MAX_PACKET ETH_MAX_PACKET + +void tuntap_user_init(void *data, void *dev) +{ + struct tuntap_data *pri = data; + + pri->dev = dev; +} + +static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, + void *data) +{ + struct tuntap_data *pri = data; + + tap_check_ips(pri->gate_addr, addr); + if((pri->fd == -1) || pri->fixed_config) return; + open_addr(addr, netmask, pri->dev_name); +} + +static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, + void *data) +{ + struct tuntap_data *pri = data; + + if((pri->fd == -1) || pri->fixed_config) return; + close_addr(addr, netmask, pri->dev_name); +} + +struct tuntap_pre_exec_data { + int stdout; + int close_me; +}; + +static void tuntap_pre_exec(void *arg) +{ + struct tuntap_pre_exec_data *data = arg; + + dup2(data->stdout, 1); + os_close_file(data->close_me); +} + +static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, + char *buffer, int buffer_len, int *used_out) +{ + struct tuntap_pre_exec_data data; + char version_buf[sizeof("nnnnn\0")]; + char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, + NULL }; + char buf[CMSG_SPACE(sizeof(*fd_out))]; + struct msghdr msg; + struct cmsghdr *cmsg; + struct iovec iov; + int pid, n; + + sprintf(version_buf, "%d", UML_NET_VERSION); + + data.stdout = remote; + data.close_me = me; + + pid = run_helper(tuntap_pre_exec, &data, argv, NULL); + + if(pid < 0) return(-pid); + + os_close_file(remote); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + if(buffer != NULL){ + iov = ((struct iovec) { buffer, buffer_len }); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + } + else { + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + } + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + msg.msg_flags = 0; + n = recvmsg(me, &msg, 0); + *used_out = n; + if(n < 0){ + printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", + errno); + return(-errno); + } + CATCH_EINTR(waitpid(pid, NULL, 0)); + + cmsg = CMSG_FIRSTHDR(&msg); + if(cmsg == NULL){ + printk("tuntap_open_tramp : didn't receive a message\n"); + return(-EINVAL); + } + if((cmsg->cmsg_level != SOL_SOCKET) || + (cmsg->cmsg_type != SCM_RIGHTS)){ + printk("tuntap_open_tramp : didn't receive a descriptor\n"); + return(-EINVAL); + } + *fd_out = ((int *) CMSG_DATA(cmsg))[0]; + return(0); +} + +static int tuntap_open(void *data) +{ + struct ifreq ifr; + struct tuntap_data *pri = data; + char *output, *buffer; + int err, fds[2], len, used; + + err = tap_open_common(pri->dev, pri->gate_addr); + if(err < 0) + return(err); + + if(pri->fixed_config){ + pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); + if(pri->fd < 0){ + printk("Failed to open /dev/net/tun, err = %d\n", + -pri->fd); + return(pri->fd); + } + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); + if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ + printk("TUNSETIFF failed, errno = %d\n", errno); + os_close_file(pri->fd); + return(-errno); + } + } + else { + err = os_pipe(fds, 0, 0); + if(err < 0){ + printk("tuntap_open : os_pipe failed - err = %d\n", + -err); + return(err); + } + + buffer = get_output_buffer(&len); + if(buffer != NULL) len--; + used = 0; + + err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], + fds[1], buffer, len, &used); + + output = buffer; + if(err < 0) { + printk("%s", output); + free_output_buffer(buffer); + printk("tuntap_open_tramp failed - err = %d\n", -err); + return(err); + } + + pri->dev_name = uml_strdup(buffer); + output += IFNAMSIZ; + printk("%s", output); + free_output_buffer(buffer); + + os_close_file(fds[0]); + iter_addresses(pri->dev, open_addr, pri->dev_name); + } + + return(pri->fd); +} + +static void tuntap_close(int fd, void *data) +{ + struct tuntap_data *pri = data; + + if(!pri->fixed_config) + iter_addresses(pri->dev, close_addr, pri->dev_name); + os_close_file(fd); + pri->fd = -1; +} + +static int tuntap_set_mtu(int mtu, void *data) +{ + return(mtu); +} + +struct net_user_info tuntap_user_info = { + .init = tuntap_user_init, + .open = tuntap_open, + .close = tuntap_close, + .remove = NULL, + .set_mtu = tuntap_set_mtu, + .add_address = tuntap_add_addr, + .delete_address = tuntap_del_addr, + .max_packet = MAX_PACKET +}; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c new file mode 100644 index 00000000000..9aee0b62ebc --- /dev/null +++ b/arch/um/os-Linux/elf_aux.c @@ -0,0 +1,66 @@ +/* + * arch/um/kernel/elf_aux.c + * + * Scan the Elf auxiliary vector provided by the host to extract + * information about vsyscall-page, etc. + * + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com) + */ +#include <elf.h> +#include <stddef.h> +#include "init.h" +#include "elf_user.h" + +#if ELF_CLASS == ELFCLASS32 +typedef Elf32_auxv_t elf_auxv_t; +#else +typedef Elf64_auxv_t elf_auxv_t; +#endif + +char * elf_aux_platform; +long elf_aux_hwcap; + +unsigned long vsyscall_ehdr; +unsigned long vsyscall_end; + +unsigned long __kernel_vsyscall; + +__init void scan_elf_aux( char **envp) +{ + long page_size = 0; + elf_auxv_t * auxv; + + while ( *envp++ != NULL) ; + + for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { + switch ( auxv->a_type ) { + case AT_SYSINFO: + __kernel_vsyscall = auxv->a_un.a_val; + break; + case AT_SYSINFO_EHDR: + vsyscall_ehdr = auxv->a_un.a_val; + break; + case AT_HWCAP: + elf_aux_hwcap = auxv->a_un.a_val; + break; + case AT_PLATFORM: + elf_aux_platform = auxv->a_un.a_ptr; + break; + case AT_PAGESZ: + page_size = auxv->a_un.a_val; + break; + } + } + if ( ! __kernel_vsyscall || ! vsyscall_ehdr || + ! elf_aux_hwcap || ! elf_aux_platform || + ! page_size || (vsyscall_ehdr % page_size) ) { + __kernel_vsyscall = 0; + vsyscall_ehdr = 0; + elf_aux_hwcap = 0; + elf_aux_platform = "i586"; + } + else { + vsyscall_end = vsyscall_ehdr + page_size; + } +} diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c new file mode 100644 index 00000000000..77d4066d1af --- /dev/null +++ b/arch/um/os-Linux/file.c @@ -0,0 +1,680 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/ioctl.h> +#include <sys/mount.h> +#include <sys/uio.h> +#include "os.h" +#include "user.h" +#include "kern_util.h" + +static void copy_stat(struct uml_stat *dst, struct stat64 *src) +{ + *dst = ((struct uml_stat) { + .ust_dev = src->st_dev, /* device */ + .ust_ino = src->st_ino, /* inode */ + .ust_mode = src->st_mode, /* protection */ + .ust_nlink = src->st_nlink, /* number of hard links */ + .ust_uid = src->st_uid, /* user ID of owner */ + .ust_gid = src->st_gid, /* group ID of owner */ + .ust_size = src->st_size, /* total size, in bytes */ + .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ + .ust_blocks = src->st_blocks, /* number of blocks allocated */ + .ust_atime = src->st_atime, /* time of last access */ + .ust_mtime = src->st_mtime, /* time of last modification */ + .ust_ctime = src->st_ctime, /* time of last change */ + }); +} + +int os_stat_fd(const int fd, struct uml_stat *ubuf) +{ + struct stat64 sbuf; + int err; + + do { + err = fstat64(fd, &sbuf); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + + if(ubuf != NULL) + copy_stat(ubuf, &sbuf); + return(err); +} + +int os_stat_file(const char *file_name, struct uml_stat *ubuf) +{ + struct stat64 sbuf; + int err; + + do { + err = stat64(file_name, &sbuf); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + + if(ubuf != NULL) + copy_stat(ubuf, &sbuf); + return(err); +} + +int os_access(const char* file, int mode) +{ + int amode, err; + + amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | + (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; + + err = access(file, amode); + if(err < 0) + return(-errno); + + return(0); +} + +void os_print_error(int error, const char* str) +{ + errno = error < 0 ? -error : error; + + perror(str); +} + +/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ +int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) +{ + int err; + + err = ioctl(fd, cmd, arg); + if(err < 0) + return(-errno); + + return(err); +} + +int os_window_size(int fd, int *rows, int *cols) +{ + struct winsize size; + + if(ioctl(fd, TIOCGWINSZ, &size) < 0) + return(-errno); + + *rows = size.ws_row; + *cols = size.ws_col; + + return(0); +} + +int os_new_tty_pgrp(int fd, int pid) +{ + if(ioctl(fd, TIOCSCTTY, 0) < 0){ + printk("TIOCSCTTY failed, errno = %d\n", errno); + return(-errno); + } + + if(tcsetpgrp(fd, pid) < 0){ + printk("tcsetpgrp failed, errno = %d\n", errno); + return(-errno); + } + + return(0); +} + +/* FIXME: ensure namebuf in os_get_if_name is big enough */ +int os_get_ifname(int fd, char* namebuf) +{ |