|
5 | 5 | */ |
6 | 6 |
|
7 | 7 | #include <asm/uaccess.h> |
8 | | - |
| 8 | +#include <linux/module.h> |
9 | 9 | #include <linux/init.h> |
10 | 10 | #include <linux/errno.h> |
11 | 11 | #include <linux/time.h> |
@@ -136,39 +136,54 @@ static const struct file_operations proc_tty_drivers_operations = { |
136 | 136 | .release = seq_release, |
137 | 137 | }; |
138 | 138 |
|
139 | | -/* |
140 | | - * This is the handler for /proc/tty/ldiscs |
141 | | - */ |
142 | | -static int tty_ldiscs_read_proc(char *page, char **start, off_t off, |
143 | | - int count, int *eof, void *data) |
| 139 | +static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
144 | 140 | { |
145 | | - int i; |
146 | | - int len = 0; |
147 | | - off_t begin = 0; |
| 141 | + return (*pos < NR_LDISCS) ? pos : NULL; |
| 142 | +} |
| 143 | + |
| 144 | +static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) |
| 145 | +{ |
| 146 | + (*pos)++; |
| 147 | + return (*pos < NR_LDISCS) ? pos : NULL; |
| 148 | +} |
| 149 | + |
| 150 | +static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) |
| 151 | +{ |
| 152 | +} |
| 153 | + |
| 154 | +static int tty_ldiscs_seq_show(struct seq_file *m, void *v) |
| 155 | +{ |
| 156 | + int i = *(loff_t *)v; |
148 | 157 | struct tty_ldisc *ld; |
149 | 158 |
|
150 | | - for (i=0; i < NR_LDISCS; i++) { |
151 | | - ld = tty_ldisc_get(i); |
152 | | - if (ld == NULL) |
153 | | - continue; |
154 | | - len += sprintf(page+len, "%-10s %2d\n", |
155 | | - ld->name ? ld->name : "???", i); |
156 | | - tty_ldisc_put(i); |
157 | | - if (len+begin > off+count) |
158 | | - break; |
159 | | - if (len+begin < off) { |
160 | | - begin += len; |
161 | | - len = 0; |
162 | | - } |
163 | | - } |
164 | | - if (i >= NR_LDISCS) |
165 | | - *eof = 1; |
166 | | - if (off >= len+begin) |
| 159 | + ld = tty_ldisc_get(i); |
| 160 | + if (ld == NULL) |
167 | 161 | return 0; |
168 | | - *start = page + (off-begin); |
169 | | - return ((count < begin+len-off) ? count : begin+len-off); |
| 162 | + seq_printf(m, "%-10s %2d\n", ld->name ? ld->name : "???", i); |
| 163 | + tty_ldisc_put(i); |
| 164 | + return 0; |
| 165 | +} |
| 166 | + |
| 167 | +static const struct seq_operations tty_ldiscs_seq_ops = { |
| 168 | + .start = tty_ldiscs_seq_start, |
| 169 | + .next = tty_ldiscs_seq_next, |
| 170 | + .stop = tty_ldiscs_seq_stop, |
| 171 | + .show = tty_ldiscs_seq_show, |
| 172 | +}; |
| 173 | + |
| 174 | +static int proc_tty_ldiscs_open(struct inode *inode, struct file *file) |
| 175 | +{ |
| 176 | + return seq_open(file, &tty_ldiscs_seq_ops); |
170 | 177 | } |
171 | 178 |
|
| 179 | +static const struct file_operations tty_ldiscs_proc_fops = { |
| 180 | + .owner = THIS_MODULE, |
| 181 | + .open = proc_tty_ldiscs_open, |
| 182 | + .read = seq_read, |
| 183 | + .llseek = seq_lseek, |
| 184 | + .release = seq_release, |
| 185 | +}; |
| 186 | + |
172 | 187 | /* |
173 | 188 | * This function is called by tty_register_driver() to handle |
174 | 189 | * registering the driver's /proc handler into /proc/tty/driver/<foo> |
@@ -223,8 +238,7 @@ void __init proc_tty_init(void) |
223 | 238 | * password lengths and inter-keystroke timings during password |
224 | 239 | * entry. |
225 | 240 | */ |
226 | | - proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR | S_IXUSR, NULL); |
227 | | - |
228 | | - create_proc_read_entry("tty/ldiscs", 0, NULL, tty_ldiscs_read_proc, NULL); |
| 241 | + proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL); |
| 242 | + proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops); |
229 | 243 | proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations); |
230 | 244 | } |
0 commit comments