OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [fs/] [proc/] [root.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/fs/proc/root.c
3
 *
4
 *  Copyright (C) 1991, 1992 Linus Torvalds
5
 *
6
 *  proc root directory handling functions
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
#include <asm/bitops.h>
17
 
18
/*
19
 * Offset of the first process in the /proc root directory..
20
 */
21
#define FIRST_PROCESS_ENTRY 256
22
 
23
static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
24
static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
25
 
26
static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
27
 
28
/*
29
 * These are the generic /proc directory operations. They
30
 * use the in-memory "struct proc_dir_entry" tree to parse
31
 * the /proc directory.
32
 *
33
 * NOTE! The /proc/scsi directory currently does not correctly
34
 * build up the proc_dir_entry tree, and will show up empty.
35
 */
36
static struct file_operations proc_dir_operations = {
37
        NULL,                   /* lseek - default */
38
        NULL,                   /* read - bad */
39
        NULL,                   /* write - bad */
40
        proc_readdir,           /* readdir */
41
        NULL,                   /* select - default */
42
        NULL,                   /* ioctl - default */
43
        NULL,                   /* mmap */
44
        NULL,                   /* no special open code */
45
        NULL,                   /* no special release code */
46
        NULL                    /* can't fsync */
47
};
48
 
49
/*
50
 * proc directories can do almost nothing..
51
 */
52
struct inode_operations proc_dir_inode_operations = {
53
        &proc_dir_operations,   /* default net directory file-ops */
54
        NULL,                   /* create */
55
        proc_lookup,            /* lookup */
56
        NULL,                   /* link */
57
        NULL,                   /* unlink */
58
        NULL,                   /* symlink */
59
        NULL,                   /* mkdir */
60
        NULL,                   /* rmdir */
61
        NULL,                   /* mknod */
62
        NULL,                   /* rename */
63
        NULL,                   /* readlink */
64
        NULL,                   /* follow_link */
65
        NULL,                   /* readpage */
66
        NULL,                   /* writepage */
67
        NULL,                   /* bmap */
68
        NULL,                   /* truncate */
69
        NULL                    /* permission */
70
};
71
 
72
/*
73
 * The root /proc directory is special, as it has the
74
 * <pid> directories. Thus we don't use the generic
75
 * directory handling functions for that..
76
 */
77
static struct file_operations proc_root_operations = {
78
        NULL,                   /* lseek - default */
79
        NULL,                   /* read - bad */
80
        NULL,                   /* write - bad */
81
        proc_root_readdir,      /* readdir */
82
        NULL,                   /* select - default */
83
        NULL,                   /* ioctl - default */
84
        NULL,                   /* mmap */
85
        NULL,                   /* no special open code */
86
        NULL,                   /* no special release code */
87
        NULL                    /* no fsync */
88
};
89
 
90
/*
91
 * proc root can do almost nothing..
92
 */
93
static struct inode_operations proc_root_inode_operations = {
94
        &proc_root_operations,  /* default base directory file-ops */
95
        NULL,                   /* create */
96
        proc_root_lookup,       /* lookup */
97
        NULL,                   /* link */
98
        NULL,                   /* unlink */
99
        NULL,                   /* symlink */
100
        NULL,                   /* mkdir */
101
        NULL,                   /* rmdir */
102
        NULL,                   /* mknod */
103
        NULL,                   /* rename */
104
        NULL,                   /* readlink */
105
        NULL,                   /* follow_link */
106
        NULL,                   /* readpage */
107
        NULL,                   /* writepage */
108
        NULL,                   /* bmap */
109
        NULL,                   /* truncate */
110
        NULL                    /* permission */
111
};
112
 
113
/*
114
 * This is the root "inode" in the /proc tree..
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
struct proc_dir_entry proc_sys_root = {
143
        PROC_SYS, 3, "sys",                     /* inode, name */
144
        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,     /* mode, nlink, uid, gid */
145
        0, &proc_dir_inode_operations,           /* size, ops */
146
        NULL, NULL,                             /* get_info, fill_inode */
147
        NULL,                                   /* next */
148
        NULL, NULL                              /* parent, subdir */
149
};
150
 
151
int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
152
{
153
        dp->next = dir->subdir;
154
        dp->parent = dir;
155
        dir->subdir = dp;
156
        if (S_ISDIR(dp->mode))
157
                dir->nlink++;
158
        return 0;
159
}
160
 
161
int proc_unregister(struct proc_dir_entry * dir, int ino)
162
{
163
        struct proc_dir_entry **p = &dir->subdir, *dp;
164
 
165
        while ((dp = *p) != NULL) {
166
                if (dp->low_ino == ino) {
167
                        *p = dp->next;
168
                        dp->next = NULL;
169
                        if (S_ISDIR(dp->mode))
170
                                dir->nlink--;
171
                        if (ino >= PROC_DYNAMIC_FIRST &&
172
                            ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
173
                                clear_bit(ino-PROC_DYNAMIC_FIRST,
174
                                          (void *) proc_alloc_map);
175
                        return 0;
176
                }
177
                p = &dp->next;
178
        }
179
        return -EINVAL;
180
}
181
 
182
static int make_inode_number(void)
183
{
184
        int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
185
        if (i<0 || i>=PROC_NDYNAMIC)
186
                return -1;
187
        set_bit(i, (void *) proc_alloc_map);
188
        return PROC_DYNAMIC_FIRST + i;
189
}
190
 
191
int proc_register_dynamic(struct proc_dir_entry * dir,
192
                          struct proc_dir_entry * dp)
193
{
194
        int i = make_inode_number();
195
        if (i < 0)
196
                return -EAGAIN;
197
        dp->low_ino = i;
198
        dp->next = dir->subdir;
199
        dp->parent = dir;
200
        dir->subdir = dp;
201
        if (S_ISDIR(dp->mode))
202
                dir->nlink++;
203
        return 0;
204
}
205
 
206
/*
207
 * /proc/self:
208
 */
209
static int proc_self_followlink(struct inode * dir, struct inode * inode,
210
                        int flag, int mode, struct inode ** res_inode)
211
{
212
        iput(dir);
213
        *res_inode = proc_get_inode(inode->i_sb, (current->pid << 16) + PROC_PID_INO, &proc_pid);
214
        iput(inode);
215
        if (!*res_inode)
216
                return -ENOENT;
217
        return 0;
218
}
219
 
220
static int proc_self_readlink(struct inode * inode, char * buffer, int buflen)
221
{
222
        int len;
223
        char tmp[30];
224
 
225
        iput(inode);
226
        len = 1 + sprintf(tmp, "%d", current->pid);
227
        if (buflen < len)
228
                len = buflen;
229
        memcpy_tofs(buffer, tmp, len);
230
        return len;
231
}
232
 
233
static struct inode_operations proc_self_inode_operations = {
234
        NULL,                   /* no file-ops */
235
        NULL,                   /* create */
236
        NULL,                   /* lookup */
237
        NULL,                   /* link */
238
        NULL,                   /* unlink */
239
        NULL,                   /* symlink */
240
        NULL,                   /* mkdir */
241
        NULL,                   /* rmdir */
242
        NULL,                   /* mknod */
243
        NULL,                   /* rename */
244
        proc_self_readlink,     /* readlink */
245
        proc_self_followlink,   /* follow_link */
246
        NULL,                   /* readpage */
247
        NULL,                   /* writepage */
248
        NULL,                   /* bmap */
249
        NULL,                   /* truncate */
250
        NULL                    /* permission */
251
};
252
 
253
struct proc_dir_entry pde_loadavg = {
254
                PROC_LOADAVG, 7, "loadavg",
255
                S_IFREG | S_IRUGO, 1, 0, 0,
256
};
257
struct proc_dir_entry pde_uptime = {
258
                PROC_UPTIME, 6, "uptime",
259
                S_IFREG | S_IRUGO, 1, 0, 0,
260
};
261
struct proc_dir_entry pde_meminfo = {
262
                PROC_MEMINFO, 7, "meminfo",
263
                S_IFREG | S_IRUGO, 1, 0, 0,
264
};
265
struct proc_dir_entry pde_serial = {
266
                PROC_SERIAL, 6, "serial",
267
                S_IFREG | S_IRUGO, 1, 0, 0,
268
};
269
struct proc_dir_entry pde_kmsg = {
270
                PROC_KMSG, 4, "kmsg",
271
                S_IFREG | S_IRUSR, 1, 0, 0,
272
};
273
struct proc_dir_entry pde_version = {
274
                PROC_VERSION, 7, "version",
275
                S_IFREG | S_IRUGO, 1, 0, 0,
276
};
277
#ifdef CONFIG_PCI
278
struct proc_dir_entry pde_pci = {
279
                PROC_PCI, 3, "pci",
280
                S_IFREG | S_IRUGO, 1, 0, 0,
281
};
282
#endif
283
struct proc_dir_entry pde_cpuinfo = {
284
                PROC_CPUINFO, 7, "cpuinfo",
285
                S_IFREG | S_IRUGO, 1, 0, 0,
286
};
287
struct proc_dir_entry pde_self = {
288
                PROC_SELF, 4, "self",
289
                S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
290
                64, &proc_self_inode_operations,
291
};
292
 
293
#ifdef CONFIG_DEBUG_MALLOC
294
struct proc_dir_entry pde_malloc = {
295
                PROC_MALLOC, 6, "malloc",
296
                S_IFREG | S_IRUGO, 1, 0, 0,
297
};
298
#endif
299
struct proc_dir_entry pde_kcore = {
300
                PROC_KCORE, 5, "kcore",
301
                S_IFREG | S_IRUSR, 1, 0, 0,
302
};
303
 
304
#ifdef CONFIG_MODULES
305
struct proc_dir_entry pde_modules = {
306
                PROC_MODULES, 7, "modules",
307
                S_IFREG | S_IRUGO, 1, 0, 0,
308
};
309
struct proc_dir_entry pde_ksyms = {
310
                PROC_KSYMS, 5, "ksyms",
311
                S_IFREG | S_IRUGO, 1, 0, 0,
312
};
313
#endif
314
struct proc_dir_entry pde_stat = {
315
                PROC_STAT, 4, "stat",
316
                S_IFREG | S_IRUGO, 1, 0, 0,
317
};
318
struct proc_dir_entry pde_devices =  {
319
                PROC_DEVICES, 7, "devices",
320
                S_IFREG | S_IRUGO, 1, 0, 0,
321
};
322
struct proc_dir_entry pde_interrupts =  {
323
                PROC_INTERRUPTS, 10,"interrupts",
324
                S_IFREG | S_IRUGO, 1, 0, 0,
325
};
326
#ifdef __SMP_PROF__
327
struct proc_dir_entry pde_smp =  {
328
                PROC_SMP_PROF, 3,"smp",
329
                S_IFREG | S_IRUGO, 1, 0, 0,
330
};
331
#endif 
332
struct proc_dir_entry pde_filesystems =  {
333
                PROC_FILESYSTEMS, 11,"filesystems",
334
                S_IFREG | S_IRUGO, 1, 0, 0,
335
};
336
struct proc_dir_entry pde_dma =  {
337
                PROC_DMA, 3, "dma",
338
                S_IFREG | S_IRUGO, 1, 0, 0,
339
};
340
struct proc_dir_entry pde_ioports =  {
341
                PROC_IOPORTS, 7, "ioports",
342
                S_IFREG | S_IRUGO, 1, 0, 0,
343
};
344
struct proc_dir_entry pde_cmdline =  {
345
                PROC_CMDLINE, 7, "cmdline",
346
                S_IFREG | S_IRUGO, 1, 0, 0,
347
};
348
#ifdef CONFIG_RTC
349
struct proc_dir_entry pde_rtc =  {
350
                PROC_RTC, 3, "rtc",
351
                S_IFREG | S_IRUGO, 1, 0, 0,
352
};
353
#endif
354
struct proc_dir_entry pde_locks =  {
355
                PROC_LOCKS, 5, "locks",
356
                S_IFREG | S_IRUGO, 1, 0, 0,
357
};
358
 
359
struct proc_dir_entry pde_mounts =
360
           { PROC_MTAB, 6, "mounts", S_IFREG | S_IRUGO, 1, 0, 0, };
361
 
362
struct proc_dir_entry pde_profile = {
363
                        PROC_PROFILE, 7, "profile",
364
                        S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
365
};
366
 
367
void proc_root_init(void)
368
{
369
        static int done = 0;
370
 
371
        if (done)
372
                return;
373
        done = 1;
374
        proc_base_init();
375
 
376
        proc_register(&proc_root, &pde_loadavg);
377
        proc_register(&proc_root, &pde_uptime);
378
        proc_register(&proc_root, &pde_meminfo);
379
        proc_register(&proc_root, &pde_kmsg);
380
        proc_register(&proc_root, &pde_version);
381
#ifdef CONFIG_PCI
382
        proc_register(&proc_root, &pde_pci);
383
#endif
384
        proc_register(&proc_root, &pde_cpuinfo);
385
        proc_register(&proc_root, &pde_self);
386
        proc_register(&proc_root, &proc_net);
387
        proc_register(&proc_root, &proc_scsi);
388
        proc_register(&proc_root, &proc_sys_root);
389
        proc_register(&proc_root, &pde_serial);
390
 
391
#ifdef CONFIG_DEBUG_MALLOC
392
        proc_register(&proc_root, &pde_malloc);
393
#endif
394
        proc_register(&proc_root, &pde_kcore);
395
 
396
#ifdef CONFIG_MODULES
397
        proc_register(&proc_root, &pde_modules);
398
        proc_register(&proc_root, &pde_ksyms);
399
#endif
400
        proc_register(&proc_root, &pde_stat);
401
        proc_register(&proc_root, &pde_devices);
402
        proc_register(&proc_root, &pde_interrupts);
403
#ifdef __SMP_PROF__
404
        proc_register(&proc_root, &pde_smp);
405
#endif 
406
        proc_register(&proc_root, &pde_filesystems);
407
        proc_register(&proc_root, &pde_dma);
408
        proc_register(&proc_root, &pde_ioports);
409
        proc_register(&proc_root, &pde_cmdline);
410
#ifdef CONFIG_RTC
411
        proc_register(&proc_root, &pde_rtc);
412
#endif
413
        proc_register(&proc_root, &pde_locks);
414
 
415
        proc_register( &proc_root, &pde_mounts);
416
 
417
        if (prof_shift) {
418
                proc_register(&proc_root, &pde_profile);
419
        }
420
}
421
 
422
 
423
int proc_match(int len,const char * name,struct proc_dir_entry * de)
424
{
425
        if (!de || !de->low_ino)
426
                return 0;
427
        /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
428
        if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
429
                return 1;
430
        if (de->namelen != len)
431
                return 0;
432
        return !memcmp(name, de->name, len);
433
}
434
 
435
int proc_lookup(struct inode * dir,const char * name, int len,
436
        struct inode ** result)
437
{
438
        struct proc_dir_entry * de;
439
        int ino;
440
 
441
        *result = NULL;
442
        if (!dir || !S_ISDIR(dir->i_mode)) {
443
                iput(dir);
444
                return -ENOTDIR;
445
        }
446
 
447
        de = (struct proc_dir_entry *) dir->u.generic_ip;
448
        if (!de) {
449
                iput(dir);
450
                return -EINVAL;
451
        }
452
 
453
        /* Special case "." and "..": they aren't on the directory list */
454
        *result = dir;
455
        if (!len)
456
                return 0;
457
        if (name[0] == '.') {
458
                if (len == 1)
459
                        return 0;
460
                if (name[1] == '.' && len == 2) {
461
                        struct inode * inode;
462
                        inode = proc_get_inode(dir->i_sb, de->parent->low_ino, de->parent);
463
                        iput(dir);
464
                        if (!inode)
465
                                return -EINVAL;
466
                        *result = inode;
467
                        return 0;
468
                }
469
        }
470
 
471
        *result = NULL;
472
        for (de = de->subdir; de ; de = de->next) {
473
                if (proc_match(len, name, de))
474
                        break;
475
        }
476
        if (!de) {
477
                iput(dir);
478
                return -ENOENT;
479
        }
480
 
481
        ino = de->low_ino | (dir->i_ino & ~(0xffff));
482
 
483
        if (!(*result = proc_get_inode(dir->i_sb, ino, de))) {
484
                iput(dir);
485
                return -EINVAL;
486
        }
487
        iput(dir);
488
        return 0;
489
}
490
 
491
static int proc_root_lookup(struct inode * dir,const char * name, int len,
492
        struct inode ** result)
493
{
494
        unsigned int pid, c;
495
        int i, ino, retval;
496
 
497
        dir->i_count++;
498
        retval = proc_lookup(dir, name, len, result);
499
        if (retval != -ENOENT) {
500
                iput(dir);
501
                return retval;
502
        }
503
 
504
        pid = 0;
505
        while (len-- > 0) {
506
                c = *name - '0';
507
                name++;
508
                if (c > 9) {
509
                        pid = 0;
510
                        break;
511
                }
512
                pid *= 10;
513
                pid += c;
514
                if (pid & 0xffff0000) {
515
                        pid = 0;
516
                        break;
517
                }
518
        }
519
        for (i = 0 ; i < NR_TASKS ; i++)
520
                if (task[i] && task[i]->pid == pid)
521
                        break;
522
        if (!pid || i >= NR_TASKS) {
523
                iput(dir);
524
                return -ENOENT;
525
        }
526
        ino = (pid << 16) + PROC_PID_INO;
527
        if (!(*result = proc_get_inode(dir->i_sb, ino, &proc_pid))) {
528
                iput(dir);
529
                return -EINVAL;
530
        }
531
        iput(dir);
532
        return 0;
533
}
534
 
535
/*
536
 * This returns non-zero if at EOF, so that the /proc
537
 * root directory can use this and check if it should
538
 * continue with the <pid> entries..
539
 *
540
 * Note that the VFS-layer doesn't care about the return
541
 * value of the readdir() call, as long as it's non-negative
542
 * for success..
543
 */
544
int proc_readdir(struct inode * inode, struct file * filp,
545
        void * dirent, filldir_t filldir)
546
{
547
        struct proc_dir_entry * de;
548
        unsigned int ino;
549
        int i;
550
 
551
        if (!inode || !S_ISDIR(inode->i_mode))
552
                return -ENOTDIR;
553
        ino = inode->i_ino;
554
        de = (struct proc_dir_entry *) inode->u.generic_ip;
555
        if (!de)
556
                return -EINVAL;
557
        i = filp->f_pos;
558
        switch (i) {
559
                case 0:
560
                        if (filldir(dirent, ".", 1, i, ino) < 0)
561
                                return 0;
562
                        i++;
563
                        filp->f_pos++;
564
                        /* fall through */
565
                case 1:
566
                        if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
567
                                return 0;
568
                        i++;
569
                        filp->f_pos++;
570
                        /* fall through */
571
                default:
572
                        ino &= ~0xffff;
573
                        de = de->subdir;
574
                        i -= 2;
575
                        for (;;) {
576
                                if (!de)
577
                                        return 1;
578
                                if (!i)
579
                                        break;
580
                                de = de->next;
581
                                i--;
582
                        }
583
 
584
                        do {
585
                                if (filldir(dirent, de->name, de->namelen, filp->f_pos, ino | de->low_ino) < 0)
586
                                        return 0;
587
                                filp->f_pos++;
588
                                de = de->next;
589
                        } while (de);
590
        }
591
        return 1;
592
}
593
 
594
#define NUMBUF 10
595
 
596
static int proc_root_readdir(struct inode * inode, struct file * filp,
597
        void * dirent, filldir_t filldir)
598
{
599
        char buf[NUMBUF];
600
        unsigned int nr,pid;
601
        unsigned long i,j;
602
 
603
        nr = filp->f_pos;
604
        if (nr < FIRST_PROCESS_ENTRY) {
605
                int error = proc_readdir(inode, filp, dirent, filldir);
606
                if (error <= 0)
607
                        return error;
608
                filp->f_pos = nr = FIRST_PROCESS_ENTRY;
609
        }
610
 
611
        for (nr -= FIRST_PROCESS_ENTRY; nr < NR_TASKS; nr++, filp->f_pos++) {
612
                struct task_struct * p = task[nr];
613
 
614
                if (!p || !(pid = p->pid))
615
                        continue;
616
 
617
                j = NUMBUF;
618
                i = pid;
619
                do {
620
                        j--;
621
                        buf[j] = '0' + (i % 10);
622
                        i /= 10;
623
                } while (i);
624
 
625
                if (filldir(dirent, buf+j, NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0)
626
                        break;
627
        }
628
        return 0;
629
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.