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