summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Viro <viro@www.linux.org.uk>2003-09-04 20:53:56 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-09-04 20:53:56 -0700
commitcbac67b10e48a7a76485d405fc723084fdafb6a1 (patch)
tree0d2c7e453d732e38766e74388c903efc37e50021
parent25a6ca892403f9d5dc2e1ed28db13e31b9fea2d2 (diff)
[PATCH] large dev_t - second series (6/15)
tty redirect handling sanitized. Such ttys (/dev/tty and /dev/console) get a different file_operations; its ->write() handles redirects; checks for file->f_op == &tty_fops updated, checks for major:minor being that of a redirector replaced with check for ->f_op->write value. Piece of code in tty_io.c that had been #if 0 since 0.99<something> had been finally put out of its misery. kdev_val() is gone.
-rw-r--r--drivers/char/n_tty.c13
-rw-r--r--drivers/char/tty_io.c126
-rw-r--r--include/linux/kdev_t.h10
3 files changed, 61 insertions, 88 deletions
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 883066efbd72..6cc938bbbf30 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -50,9 +50,6 @@
#include <asm/system.h>
#include <asm/bitops.h>
-#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
-#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
-
/* number of characters left in xmit buffer before select has we have room */
#define WAKEUP_CHARS 256
@@ -951,6 +948,8 @@ static inline int copy_from_read_buf(struct tty_struct *tty,
return retval;
}
+extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *);
+
static ssize_t read_chan(struct tty_struct *tty, struct file *file,
unsigned char *buf, size_t nr)
{
@@ -975,9 +974,7 @@ do_it_again:
/* NOTE: not yet done after every sleep pending a thorough
check of the logic of this change. -- jlc */
/* don't stop on /dev/console */
- if (!IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) &&
- !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev) &&
- current->tty == tty) {
+ if (file->f_op->write != redirected_tty_write && current->tty == tty) {
if (tty->pgrp <= 0)
printk("read_chan: tty->pgrp <= 0!\n");
else if (current->pgrp != tty->pgrp) {
@@ -1168,9 +1165,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
ssize_t retval = 0;
/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
- if (L_TOSTOP(tty) &&
- !IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) &&
- !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev)) {
+ if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) {
retval = tty_check_change(tty);
if (retval)
return retval;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 83640a923209..a1888c4dc0d9 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -103,11 +103,6 @@
#include <linux/kmod.h>
-#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0))
-#define IS_TTY_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,0))
-#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1))
-#define IS_PTMX_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,2))
-
#undef TTY_DEBUG_HANGUP
#define TTY_PARANOIA_CHECK 1
@@ -136,6 +131,7 @@ static void initialize_tty_struct(struct tty_struct *tty);
static ssize_t tty_read(struct file *, char *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);
+ssize_t redirected_tty_write(struct file *, const char *, size_t, loff_t *);
static unsigned int tty_poll(struct file *, poll_table *);
static int tty_open(struct inode *, struct file *);
static int tty_release(struct inode *, struct file *);
@@ -382,6 +378,17 @@ static struct file_operations tty_fops = {
.fasync = tty_fasync,
};
+static struct file_operations console_fops = {
+ .llseek = no_llseek,
+ .read = tty_read,
+ .write = redirected_tty_write,
+ .poll = tty_poll,
+ .ioctl = tty_ioctl,
+ .open = tty_open,
+ .release = tty_release,
+ .fasync = tty_fasync,
+};
+
static struct file_operations hung_up_tty_fops = {
.llseek = no_llseek,
.read = hung_up_tty_read,
@@ -425,12 +432,9 @@ void do_tty_hangup(void *data)
check_tty_count(tty, "do_tty_hangup");
file_list_lock();
list_for_each_entry(filp, &tty->tty_files, f_list) {
- if (IS_CONSOLE_DEV(filp->f_dentry->d_inode->i_rdev) ||
- IS_SYSCONS_DEV(filp->f_dentry->d_inode->i_rdev)) {
+ if (filp->f_op->write == redirected_tty_write)
cons_filp = filp;
- continue;
- }
- if (filp->f_op != &tty_fops)
+ if (filp->f_op->write != tty_write)
continue;
closecount++;
tty_fasync(-1, filp, 0); /* can't block */
@@ -650,22 +654,6 @@ static ssize_t tty_read(struct file * file, char * buf, size_t count,
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
return -EIO;
- /* This check not only needs to be done before reading, but also
- whenever read_chan() gets woken up after sleeping, so I've
- moved it to there. This should only be done for the N_TTY
- line discipline, anyway. Same goes for write_chan(). -- jlc. */
-#if 0
- if (!IS_CONSOLE_DEV(inode->i_rdev) && /* don't stop on /dev/console */
- (tty->pgrp > 0) &&
- (current->tty == tty) &&
- (tty->pgrp != current->pgrp))
- if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp))
- return -EIO;
- else {
- (void) kill_pg(current->pgrp, SIGTTIN, 1);
- return -ERESTARTSYS;
- }
-#endif
lock_kernel();
if (tty->ldisc.read)
i = (tty->ldisc.read)(tty,file,buf,count);
@@ -730,37 +718,13 @@ static inline ssize_t do_tty_write(
static ssize_t tty_write(struct file * file, const char * buf, size_t count,
loff_t *ppos)
{
- int is_console;
struct tty_struct * tty;
struct inode *inode = file->f_dentry->d_inode;
- /*
- * For now, we redirect writes from /dev/console as
- * well as /dev/tty0.
- */
- is_console = IS_SYSCONS_DEV(inode->i_rdev) ||
- IS_CONSOLE_DEV(inode->i_rdev);
/* Can't seek (pwrite) on ttys. */
if (ppos != &file->f_pos)
return -ESPIPE;
- if (is_console) {
- struct file *p = NULL;
-
- spin_lock(&redirect_lock);
- if (redirect) {
- get_file(redirect);
- p = redirect;
- }
- spin_unlock(&redirect_lock);
-
- if (p) {
- ssize_t res = vfs_write(p, buf, count, &p->f_pos);
- fput(p);
- return res;
- }
- }
-
tty = (struct tty_struct *)file->private_data;
if (tty_paranoia_check(tty, inode, "tty_write"))
return -EIO;
@@ -772,6 +736,31 @@ static ssize_t tty_write(struct file * file, const char * buf, size_t count,
(const unsigned char *)buf, count);
}
+ssize_t redirected_tty_write(struct file * file, const char * buf, size_t count,
+ loff_t *ppos)
+{
+ struct file *p = NULL;
+
+ spin_lock(&redirect_lock);
+ if (redirect) {
+ get_file(redirect);
+ p = redirect;
+ }
+ spin_unlock(&redirect_lock);
+
+ if (p) {
+ ssize_t res;
+ /* Can't seek (pwrite) on ttys. */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+ res = vfs_write(p, buf, count, &p->f_pos);
+ fput(p);
+ return res;
+ }
+
+ return tty_write(file, buf, count, ppos);
+}
+
/* Semaphore to protect creating and releasing a tty */
static DECLARE_MUTEX(tty_sem);
@@ -1306,14 +1295,11 @@ static int tty_open(struct inode * inode, struct file * filp)
int noctty, retval;
struct tty_driver *driver;
int index;
- kdev_t device;
- unsigned short saved_flags;
-
- saved_flags = filp->f_flags;
+ dev_t device = kdev_t_to_nr(inode->i_rdev);
+ unsigned short saved_flags = filp->f_flags;
retry_open:
noctty = filp->f_flags & O_NOCTTY;
- device = inode->i_rdev;
- if (IS_TTY_DEV(device)) {
+ if (device == MKDEV(TTYAUX_MAJOR,0)) {
if (!current->tty)
return -ENXIO;
driver = current->tty->driver;
@@ -1323,7 +1309,7 @@ retry_open:
goto got_driver;
}
#ifdef CONFIG_VT
- if (IS_CONSOLE_DEV(device)) {
+ if (device == MKDEV(TTY_MAJOR,0)) {
extern int fg_console;
extern struct tty_driver *console_driver;
driver = console_driver;
@@ -1332,7 +1318,7 @@ retry_open:
goto got_driver;
}
#endif
- if (IS_SYSCONS_DEV(device)) {
+ if (device == MKDEV(TTYAUX_MAJOR,1)) {
struct console *c = console_drivers;
for (c = console_drivers; c; c = c->next) {
if (!c->device)
@@ -1348,7 +1334,7 @@ retry_open:
return -ENODEV;
}
- if (IS_PTMX_DEV(device)) {
+ if (device == MKDEV(TTYAUX_MAJOR,2)) {
#ifdef CONFIG_UNIX98_PTYS
/* find a device that is not in use. */
retval = -1;
@@ -1365,7 +1351,7 @@ retry_open:
return -ENODEV;
#endif /* CONFIG_UNIX_98_PTYS */
} else {
- driver = get_tty_driver(kdev_t_to_nr(device), &index);
+ driver = get_tty_driver(device, &index);
if (!driver)
return -ENODEV;
got_driver:
@@ -1407,7 +1393,8 @@ got_driver:
/*
* Need to reset f_op in case a hangup happened.
*/
- filp->f_op = &tty_fops;
+ if (filp->f_op == &hung_up_tty_fops)
+ filp->f_op = &tty_fops;
goto retry_open;
}
if (!noctty &&
@@ -1516,10 +1503,9 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
return 0;
}
-static int tioccons(struct inode *inode, struct file *file)
+static int tioccons(struct file *file)
{
- if (IS_SYSCONS_DEV(inode->i_rdev) ||
- IS_CONSOLE_DEV(inode->i_rdev)) {
+ if (file->f_op->write == redirected_tty_write) {
struct file *f;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -1786,7 +1772,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
case TIOCSWINSZ:
return tiocswinsz(tty, real_tty, (struct winsize *) arg);
case TIOCCONS:
- return real_tty!=tty ? -EINVAL : tioccons(inode, file);
+ return real_tty!=tty ? -EINVAL : tioccons(file);
case FIONBIO:
return fionbio(file, (int *) arg);
case TIOCEXCL:
@@ -1917,8 +1903,10 @@ static void __do_SAK(void *arg)
spin_lock(&p->files->file_lock);
for (i=0; i < p->files->max_fds; i++) {
filp = fcheck_files(p->files, i);
- if (filp && (filp->f_op == &tty_fops) &&
- (filp->private_data == tty)) {
+ if (!filp)
+ continue;
+ if (filp->f_op->read == tty_read &&
+ filp->private_data == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): fd#%d opened to the tty\n",
p->pid, p->comm, i);
@@ -2446,7 +2434,7 @@ void __init tty_init(void)
tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
strcpy(console_cdev.kobj.name, "dev.console");
- cdev_init(&console_cdev, &tty_fops);
+ cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
@@ -2468,7 +2456,7 @@ void __init tty_init(void)
#ifdef CONFIG_VT
strcpy(vc0_cdev.kobj.name, "dev.vc0");
- cdev_init(&vc0_cdev, &tty_fops);
+ cdev_init(&vc0_cdev, &console_fops);
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h
index 900a4a1e1282..64a88b3b194a 100644
--- a/include/linux/kdev_t.h
+++ b/include/linux/kdev_t.h
@@ -80,16 +80,6 @@ typedef struct {
#define mk_kdev(major, minor) ((kdev_t) { __mkdev(major,minor) } )
-/*
- * The "values" are just _cookies_, usable for
- * internal equality comparisons and for things
- * like NFS filehandle conversion.
- */
-static inline unsigned int kdev_val(kdev_t dev)
-{
- return dev.value;
-}
-
#define NODEV (mk_kdev(0,0))
/* Mask off the high bits for now.. */