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