mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 00:48:50 +00:00
43f5b3085f
Reintroduce uml_kmalloc for the benefit of UML libc code. The previous tactic of declaring __kmalloc so it could be called directly from the libc side of the house turned out to be getting too intimate with slab, and it doesn't work with slob. So, the uml_kmalloc wrapper is back. It calls kmalloc or whatever that translates into, and libc code calls it. kfree is left alone since that still works, leaving a somewhat inconsistent API. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Cc: WANG Cong <xiyou.wangcong@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
83 lines
1.5 KiB
C
83 lines
1.5 KiB
C
/*
|
|
* Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
|
|
* Licensed under the GPL
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include "chan_user.h"
|
|
#include "kern_constants.h"
|
|
#include "os.h"
|
|
#include "um_malloc.h"
|
|
#include "user.h"
|
|
|
|
struct tty_chan {
|
|
char *dev;
|
|
int raw;
|
|
struct termios tt;
|
|
};
|
|
|
|
static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
|
|
{
|
|
struct tty_chan *data;
|
|
|
|
if (*str != ':') {
|
|
printk(UM_KERN_ERR "tty_init : channel type 'tty' must specify "
|
|
"a device\n");
|
|
return NULL;
|
|
}
|
|
str++;
|
|
|
|
data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
|
|
if (data == NULL)
|
|
return NULL;
|
|
*data = ((struct tty_chan) { .dev = str,
|
|
.raw = opts->raw });
|
|
|
|
return data;
|
|
}
|
|
|
|
static int tty_open(int input, int output, int primary, void *d,
|
|
char **dev_out)
|
|
{
|
|
struct tty_chan *data = d;
|
|
int fd, err, mode = 0;
|
|
|
|
if (input && output)
|
|
mode = O_RDWR;
|
|
else if (input)
|
|
mode = O_RDONLY;
|
|
else if (output)
|
|
mode = O_WRONLY;
|
|
|
|
fd = open(data->dev, mode);
|
|
if (fd < 0)
|
|
return -errno;
|
|
|
|
if (data->raw) {
|
|
CATCH_EINTR(err = tcgetattr(fd, &data->tt));
|
|
if (err)
|
|
return err;
|
|
|
|
err = raw(fd);
|
|
if (err)
|
|
return err;
|
|
}
|
|
|
|
*dev_out = data->dev;
|
|
return fd;
|
|
}
|
|
|
|
const struct chan_ops tty_ops = {
|
|
.type = "tty",
|
|
.init = tty_chan_init,
|
|
.open = tty_open,
|
|
.close = generic_close,
|
|
.read = generic_read,
|
|
.write = generic_write,
|
|
.console_write = generic_console_write,
|
|
.window_size = generic_window_size,
|
|
.free = generic_free,
|
|
.winch = 0,
|
|
};
|