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#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <linux/proc_fs.h>
38#include <linux/jiffies.h>
39#include <asm/uaccess.h>
40
41
42#define MODULE_VERS "1.0"
43#define MODULE_NAME "procfs_example"
44
45#define FOOBAR_LEN 8
46
47struct fb_data_t {
48 char name[FOOBAR_LEN + 1];
49 char value[FOOBAR_LEN + 1];
50};
51
52
53static struct proc_dir_entry *example_dir, *foo_file,
54 *bar_file, *jiffies_file, *symlink;
55
56
57struct fb_data_t foo_data, bar_data;
58
59
60static int proc_read_jiffies(char *page, char **start,
61 off_t off, int count,
62 int *eof, void *data)
63{
64 int len;
65
66 len = sprintf(page, "jiffies = %ld\n",
67 jiffies);
68
69 return len;
70}
71
72
73static int proc_read_foobar(char *page, char **start,
74 off_t off, int count,
75 int *eof, void *data)
76{
77 int len;
78 struct fb_data_t *fb_data = (struct fb_data_t *)data;
79
80
81 len = sprintf(page, "%s = '%s'\n",
82 fb_data->name, fb_data->value);
83
84 return len;
85}
86
87
88static int proc_write_foobar(struct file *file,
89 const char *buffer,
90 unsigned long count,
91 void *data)
92{
93 int len;
94 struct fb_data_t *fb_data = (struct fb_data_t *)data;
95
96 if(count > FOOBAR_LEN)
97 len = FOOBAR_LEN;
98 else
99 len = count;
100
101 if(copy_from_user(fb_data->value, buffer, len))
102 return -EFAULT;
103
104 fb_data->value[len] = '\0';
105
106 return len;
107}
108
109
110static int __init init_procfs_example(void)
111{
112 int rv = 0;
113
114
115 example_dir = proc_mkdir(MODULE_NAME, NULL);
116 if(example_dir == NULL) {
117 rv = -ENOMEM;
118 goto out;
119 }
120
121 jiffies_file = create_proc_read_entry("jiffies",
122 0444, example_dir,
123 proc_read_jiffies,
124 NULL);
125 if(jiffies_file == NULL) {
126 rv = -ENOMEM;
127 goto no_jiffies;
128 }
129
130
131
132
133 foo_file = create_proc_entry("foo", 0644, example_dir);
134 if(foo_file == NULL) {
135 rv = -ENOMEM;
136 goto no_foo;
137 }
138
139 strcpy(foo_data.name, "foo");
140 strcpy(foo_data.value, "foo");
141 foo_file->data = &foo_data;
142 foo_file->read_proc = proc_read_foobar;
143 foo_file->write_proc = proc_write_foobar;
144
145 bar_file = create_proc_entry("bar", 0644, example_dir);
146 if(bar_file == NULL) {
147 rv = -ENOMEM;
148 goto no_bar;
149 }
150
151 strcpy(bar_data.name, "bar");
152 strcpy(bar_data.value, "bar");
153 bar_file->data = &bar_data;
154 bar_file->read_proc = proc_read_foobar;
155 bar_file->write_proc = proc_write_foobar;
156
157
158 symlink = proc_symlink("jiffies_too", example_dir,
159 "jiffies");
160 if(symlink == NULL) {
161 rv = -ENOMEM;
162 goto no_symlink;
163 }
164
165
166 printk(KERN_INFO "%s %s initialised\n",
167 MODULE_NAME, MODULE_VERS);
168 return 0;
169
170no_symlink:
171 remove_proc_entry("bar", example_dir);
172no_bar:
173 remove_proc_entry("foo", example_dir);
174no_foo:
175 remove_proc_entry("jiffies", example_dir);
176no_jiffies:
177 remove_proc_entry(MODULE_NAME, NULL);
178out:
179 return rv;
180}
181
182
183static void __exit cleanup_procfs_example(void)
184{
185 remove_proc_entry("jiffies_too", example_dir);
186 remove_proc_entry("bar", example_dir);
187 remove_proc_entry("foo", example_dir);
188 remove_proc_entry("jiffies", example_dir);
189 remove_proc_entry(MODULE_NAME, NULL);
190
191 printk(KERN_INFO "%s %s removed\n",
192 MODULE_NAME, MODULE_VERS);
193}
194
195
196module_init(init_procfs_example);
197module_exit(cleanup_procfs_example);
198
199MODULE_AUTHOR("Erik Mouw");
200MODULE_DESCRIPTION("procfs examples");
201MODULE_LICENSE("GPL");
202