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