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