This source file includes following definitions.
- proc_register
- proc_unregister
- proc_self_followlink
- proc_self_readlink
- proc_root_init
- proc_match
- proc_lookup
- proc_root_lookup
- proc_readdir
- proc_root_readdir
1
2
3
4
5
6
7
8
9 #include <asm/segment.h>
10
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/proc_fs.h>
14 #include <linux/stat.h>
15 #include <linux/config.h>
16
17
18
19
20 #define FIRST_PROCESS_ENTRY 256
21
22 static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
23 static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
24
25 static struct file_operations proc_root_operations = {
26 NULL,
27 NULL,
28 NULL,
29 proc_root_readdir,
30 NULL,
31 NULL,
32 NULL,
33 NULL,
34 NULL,
35 NULL
36 };
37
38
39
40
41 static struct inode_operations proc_root_inode_operations = {
42 &proc_root_operations,
43 NULL,
44 proc_root_lookup,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 NULL,
56 NULL
57 };
58
59
60
61
62 struct proc_dir_entry proc_root = {
63 PROC_ROOT_INO, 5, "/proc",
64 S_IFDIR | S_IRUGO | S_IXUGO, 3, 0, 0,
65 0, &proc_root_inode_operations,
66 NULL, NULL,
67 NULL,
68 &proc_root, NULL
69 };
70
71 int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
72 {
73 dp->next = dir->subdir;
74 dp->parent = dir;
75 dir->subdir = dp;
76 if (S_ISDIR(dp->mode))
77 dir->nlink++;
78 return 0;
79 }
80
81 int proc_unregister(struct proc_dir_entry * dir, int ino)
82 {
83 struct proc_dir_entry **p = &dir->subdir, *dp;
84
85 while ((dp = *p) != NULL) {
86 if (dp->low_ino == ino) {
87 *p = dp->next;
88 dp->next = NULL;
89 if (S_ISDIR(dp->mode))
90 dir->nlink--;
91 return 0;
92 }
93 p = &dp->next;
94 }
95 return -EINVAL;
96 }
97
98
99
100
101 static int proc_self_followlink(struct inode * dir, struct inode * inode,
102 int flag, int mode, struct inode ** res_inode)
103 {
104 iput(dir);
105 *res_inode = proc_get_inode(inode->i_sb, (current->pid << 16) + PROC_PID_INO, &proc_pid);
106 iput(inode);
107 if (!*res_inode)
108 return -ENOENT;
109 return 0;
110 }
111
112 static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
113 {
114 int len;
115 char tmp[30];
116
117 iput(inode);
118 len = 1 + sprintf(tmp, "%d", current->pid);
119 if (buflen < len)
120 len = buflen;
121 memcpy_tofs(buffer, tmp, len);
122 return len;
123 }
124
125 static struct inode_operations proc_self_inode_operations = {
126 NULL,
127 NULL,
128 NULL,
129 NULL,
130 NULL,
131 NULL,
132 NULL,
133 NULL,
134 NULL,
135 NULL,
136 proc_self_readlink,
137 proc_self_followlink,
138 NULL,
139 NULL,
140 NULL
141 };
142
143 void proc_root_init(void)
144 {
145 static int done = 0;
146
147 if (done)
148 return;
149 done = 1;
150 proc_base_init();
151 proc_register(&proc_root, &(struct proc_dir_entry) {
152 PROC_LOADAVG, 7, "loadavg",
153 S_IFREG | S_IRUGO, 1, 0, 0,
154 });
155 proc_register(&proc_root, &(struct proc_dir_entry) {
156 PROC_UPTIME, 6, "uptime",
157 S_IFREG | S_IRUGO, 1, 0, 0,
158 });
159 proc_register(&proc_root, &(struct proc_dir_entry) {
160 PROC_MEMINFO, 7, "meminfo",
161 S_IFREG | S_IRUGO, 1, 0, 0,
162 });
163 proc_register(&proc_root, &(struct proc_dir_entry) {
164 PROC_KMSG, 4, "kmsg",
165 S_IFREG | S_IRUSR, 1, 0, 0,
166 });
167 proc_register(&proc_root, &(struct proc_dir_entry) {
168 PROC_VERSION, 7, "version",
169 S_IFREG | S_IRUGO, 1, 0, 0,
170 });
171 #ifdef CONFIG_PCI
172 proc_register(&proc_root, &(struct proc_dir_entry) {
173 PROC_PCI, 3, "pci",
174 S_IFREG | S_IRUGO, 1, 0, 0,
175 });
176 #endif
177 proc_register(&proc_root, &(struct proc_dir_entry) {
178 PROC_CPUINFO, 7, "cpuinfo",
179 S_IFREG | S_IRUGO, 1, 0, 0,
180 });
181 proc_register(&proc_root, &(struct proc_dir_entry) {
182 PROC_SELF, 4, "self",
183 S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
184 64, &proc_self_inode_operations,
185 });
186 proc_register(&proc_root, &proc_net);
187 proc_register(&proc_root, &proc_scsi);
188 #ifdef CONFIG_DEBUG_MALLOC
189 proc_register(&proc_root, &(struct proc_dir_entry) {
190 PROC_MALLOC, 6, "malloc",
191 S_IFREG | S_IRUGO, 1, 0, 0,
192 });
193 #endif
194 proc_register(&proc_root, &(struct proc_dir_entry) {
195 PROC_KCORE, 5, "kcore",
196 S_IFREG | S_IRUSR, 1, 0, 0,
197 });
198 proc_register(&proc_root, &(struct proc_dir_entry) {
199 PROC_MODULES, 7, "modules",
200 S_IFREG | S_IRUGO, 1, 0, 0,
201 });
202 proc_register(&proc_root, &(struct proc_dir_entry) {
203 PROC_STAT, 4, "stat",
204 S_IFREG | S_IRUGO, 1, 0, 0,
205 });
206 proc_register(&proc_root, &(struct proc_dir_entry) {
207 PROC_DEVICES, 7, "devices",
208 S_IFREG | S_IRUGO, 1, 0, 0,
209 });
210 proc_register(&proc_root, &(struct proc_dir_entry) {
211 PROC_INTERRUPTS, 10,"interrupts",
212 S_IFREG | S_IRUGO, 1, 0, 0,
213 });
214 proc_register(&proc_root, &(struct proc_dir_entry) {
215 PROC_FILESYSTEMS, 11,"filesystems",
216 S_IFREG | S_IRUGO, 1, 0, 0,
217 });
218 proc_register(&proc_root, &(struct proc_dir_entry) {
219 PROC_KSYMS, 5, "ksyms",
220 S_IFREG | S_IRUGO, 1, 0, 0,
221 });
222 proc_register(&proc_root, &(struct proc_dir_entry) {
223 PROC_DMA, 3, "dma",
224 S_IFREG | S_IRUGO, 1, 0, 0,
225 });
226 proc_register(&proc_root, &(struct proc_dir_entry) {
227 PROC_IOPORTS, 7, "ioports",
228 S_IFREG | S_IRUGO, 1, 0, 0,
229 });
230 #ifdef CONFIG_PROFILE
231 proc_register(&proc_root, &(struct proc_dir_entry) {
232 PROC_PROFILE, 7, "profile",
233 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
234 });
235 #endif
236 }
237
238
239 int proc_match(int len,const char * name,struct proc_dir_entry * de)
240 {
241 if (!de || !de->low_ino)
242 return 0;
243
244 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
245 return 1;
246 if (de->namelen != len)
247 return 0;
248 return !memcmp(name, de->name, len);
249 }
250
251 int proc_lookup(struct inode * dir,const char * name, int len,
252 struct inode ** result)
253 {
254 struct proc_dir_entry * de;
255 int ino;
256
257 *result = NULL;
258 if (!dir || !S_ISDIR(dir->i_mode)) {
259 iput(dir);
260 return -ENOTDIR;
261 }
262
263 de = (struct proc_dir_entry *) dir->u.generic_ip;
264 if (!de)
265 return -EINVAL;
266
267
268 *result = dir;
269 if (!len)
270 return 0;
271 if (name[0] == '.') {
272 if (len == 1)
273 return 0;
274 if (name[1] == '.' && len == 2) {
275 struct inode * inode;
276 inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent);
277 iput(dir);
278 if (!inode)
279 return -EINVAL;
280 *result = inode;
281 return 0;
282 }
283 }
284
285 *result = NULL;
286 for (de = de->subdir; de ; de = de->next) {
287 if (proc_match(len, name, de))
288 break;
289 }
290 if (!de)
291 return -ENOENT;
292
293 ino = de->low_ino | (dir->i_ino & ~(0xffff));
294
295 if (!(*result = proc_get_inode(dir->i_sb, ino, de))) {
296 iput(dir);
297 return -EINVAL;
298 }
299 iput(dir);
300 return 0;
301 }
302
303 static int proc_root_lookup(struct inode * dir,const char * name, int len,
304 struct inode ** result)
305 {
306 unsigned int pid, c;
307 int i, ino;
308
309 int retval = proc_lookup(dir, name, len, result);
310 if (retval != -ENOENT)
311 return retval;
312
313 pid = 0;
314 while (len-- > 0) {
315 c = *name - '0';
316 name++;
317 if (c > 9) {
318 pid = 0;
319 break;
320 }
321 pid *= 10;
322 pid += c;
323 if (pid & 0xffff0000) {
324 pid = 0;
325 break;
326 }
327 }
328 for (i = 0 ; i < NR_TASKS ; i++)
329 if (task[i] && task[i]->pid == pid)
330 break;
331 if (!pid || i >= NR_TASKS) {
332 iput(dir);
333 return -ENOENT;
334 }
335 ino = (pid << 16) + PROC_PID_INO;
336 if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) {
337 iput(dir);
338 return -EINVAL;
339 }
340 iput(dir);
341 return 0;
342 }
343
344
345
346
347
348
349
350
351
352
353 int proc_readdir(struct inode * inode, struct file * filp,
354 void * dirent, filldir_t filldir)
355 {
356 struct proc_dir_entry * de;
357 unsigned int ino;
358 int i;
359
360 if (!inode || !S_ISDIR(inode->i_mode))
361 return -ENOTDIR;
362 ino = inode->i_ino;
363 de = (struct proc_dir_entry *) inode->u.generic_ip;
364 if (!de)
365 return -EINVAL;
366 i = filp->f_pos;
367 switch (i) {
368 case 0:
369 if (filldir(dirent, ".", 1, i, ino) < 0)
370 return 0;
371 i++;
372 filp->f_pos++;
373
374 case 1:
375 if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
376 return 0;
377 i++;
378 filp->f_pos++;
379
380 default:
381 ino &= ~0xffff;
382 de = de->subdir;
383 i -= 2;
384 for (;;) {
385 if (!de)
386 return 1;
387 if (!i)
388 break;
389 de = de->next;
390 i--;
391 }
392
393 do {
394 if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0)
395 return 0;
396 filp->f_pos++;
397 de = de->next;
398 } while (de);
399 }
400 return 1;
401 }
402
403 #define NUMBUF 10
404
405 static int proc_root_readdir(struct inode * inode, struct file * filp,
406 void * dirent, filldir_t filldir)
407 {
408 char buf[NUMBUF];
409 unsigned int nr,pid;
410 unsigned long i,j;
411
412 nr = filp->f_pos;
413 if (nr < FIRST_PROCESS_ENTRY) {
414 int error = proc_readdir(inode, filp, dirent, filldir);
415 if (error <= 0)
416 return error;
417 filp->f_pos = nr = FIRST_PROCESS_ENTRY;
418 }
419
420 for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) {
421 struct task_struct * p = task[nr];
422
423 if (!p || !(pid = p->pid))
424 continue;
425
426 j = NUMBUF;
427 i = pid;
428 do {
429 j--;
430 buf[j] = '0' + (i % 10);
431 i /= 10;
432 } while (i);
433
434 if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0)
435 break;
436 }
437 return 0;
438 }