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
296 if (prof_shift) {
297 proc_register(&proc_root, &(struct proc_dir_entry) {
298 PROC_PROFILE, 7, "profile",
299 S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
300 });
301 }
302 }
303
304
305 int proc_match(int len,const char * name,struct proc_dir_entry * de)
306 {
307 if (!de || !de->low_ino)
308 return 0;
309
310 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
311 return 1;
312 if (de->namelen != len)
313 return 0;
314 return !memcmp(name, de->name, len);
315 }
316
317 int proc_lookup(struct inode * dir,const char * name, int len,
318 struct inode ** result)
319 {
320 struct proc_dir_entry * de;
321 int ino;
322
323 *result = NULL;
324 if (!dir || !S_ISDIR(dir->i_mode)) {
325 iput(dir);
326 return -ENOTDIR;
327 }
328
329 de = (struct proc_dir_entry *) dir->u.generic_ip;
330 if (!de)
331 return -EINVAL;
332
333
334 *result = dir;
335 if (!len)
336 return 0;
337 if (name[0] == '.') {
338 if (len == 1)
339 return 0;
340 if (name[1] == '.' && len == 2) {
341 struct inode * inode;
342 inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent);
343 iput(dir);
344 if (!inode)
345 return -EINVAL;
346 *result = inode;
347 return 0;
348 }
349 }
350
351 *result = NULL;
352 for (de = de->subdir; de ; de = de->next) {
353 if (proc_match(len, name, de))
354 break;
355 }
356 if (!de)
357 return -ENOENT;
358
359 ino = de->low_ino | (dir->i_ino & ~(0xffff));
360
361 if (!(*result = proc_get_inode(dir->i_sb, ino, de))) {
362 iput(dir);
363 return -EINVAL;
364 }
365 iput(dir);
366 return 0;
367 }
368
369 static int proc_root_lookup(struct inode * dir,const char * name, int len,
370 struct inode ** result)
371 {
372 unsigned int pid, c;
373 int i, ino;
374
375 int retval = proc_lookup(dir, name, len, result);
376 if (retval != -ENOENT)
377 return retval;
378
379 pid = 0;
380 while (len-- > 0) {
381 c = *name - '0';
382 name++;
383 if (c > 9) {
384 pid = 0;
385 break;
386 }
387 pid *= 10;
388 pid += c;
389 if (pid & 0xffff0000) {
390 pid = 0;
391 break;
392 }
393 }
394 for (i = 0 ; i < NR_TASKS ; i++)
395 if (task[i] && task[i]->pid == pid)
396 break;
397 if (!pid || i >= NR_TASKS) {
398 iput(dir);
399 return -ENOENT;
400 }
401 ino = (pid << 16) + PROC_PID_INO;
402 if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) {
403 iput(dir);
404 return -EINVAL;
405 }
406 iput(dir);
407 return 0;
408 }
409
410
411
412
413
414
415
416
417
418
419 int proc_readdir(struct inode * inode, struct file * filp,
420 void * dirent, filldir_t filldir)
421 {
422 struct proc_dir_entry * de;
423 unsigned int ino;
424 int i;
425
426 if (!inode || !S_ISDIR(inode->i_mode))
427 return -ENOTDIR;
428 ino = inode->i_ino;
429 de = (struct proc_dir_entry *) inode->u.generic_ip;
430 if (!de)
431 return -EINVAL;
432 i = filp->f_pos;
433 switch (i) {
434 case 0:
435 if (filldir(dirent, ".", 1, i, ino) < 0)
436 return 0;
437 i++;
438 filp->f_pos++;
439
440 case 1:
441 if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
442 return 0;
443 i++;
444 filp->f_pos++;
445
446 default:
447 ino &= ~0xffff;
448 de = de->subdir;
449 i -= 2;
450 for (;;) {
451 if (!de)
452 return 1;
453 if (!i)
454 break;
455 de = de->next;
456 i--;
457 }
458
459 do {
460 if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0)
461 return 0;
462 filp->f_pos++;
463 de = de->next;
464 } while (de);
465 }
466 return 1;
467 }
468
469 #define NUMBUF 10
470
471 static int proc_root_readdir(struct inode * inode, struct file * filp,
472 void * dirent, filldir_t filldir)
473 {
474 char buf[NUMBUF];
475 unsigned int nr,pid;
476 unsigned long i,j;
477
478 nr = filp->f_pos;
479 if (nr < FIRST_PROCESS_ENTRY) {
480 int error = proc_readdir(inode, filp, dirent, filldir);
481 if (error <= 0)
482 return error;
483 filp->f_pos = nr = FIRST_PROCESS_ENTRY;
484 }
485
486 for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) {
487 struct task_struct * p = task[nr];
488
489 if (!p || !(pid = p->pid))
490 continue;
491
492 j = NUMBUF;
493 i = pid;
494 do {
495 j--;
496 buf[j] = '0' + (i % 10);
497 i /= 10;
498 } while (i);
499
500 if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0)
501 break;
502 }
503 return 0;
504 }