home *** CD-ROM | disk | FTP | other *** search
- /*
- * linux/fs/proc/root.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * proc root directory handling functions
- */
-
- #include <asm/segment.h>
-
- #include <linux/errno.h>
- #include <linux/sched.h>
- #include <linux/proc_fs.h>
- #include <linux/stat.h>
- #include <linux/config.h>
-
- static int proc_readroot(struct inode *, struct file *, struct dirent *, int);
- static int proc_lookuproot(struct inode *,const char *,int,struct inode **);
-
- static struct file_operations proc_root_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- proc_readroot, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special release code */
- NULL /* no fsync */
- };
-
- /*
- * proc directories can do almost nothing..
- */
- struct inode_operations proc_root_inode_operations = {
- &proc_root_operations, /* default base directory file-ops */
- NULL, /* create */
- proc_lookuproot, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
- };
-
- static struct proc_dir_entry root_dir[] = {
- { 1,1,"." },
- { 1,2,".." },
- { 2,7,"loadavg" },
- { 3,6,"uptime" },
- { 4,7,"meminfo" },
- { 5,4,"kmsg" },
- { 6,7,"version" },
- { 7,4,"self" }, /* will change inode # */
- { 8,3,"net" },
- #ifdef CONFIG_DEBUG_MALLOC
- {13,6,"malloc" },
- #endif
- {14,5,"kcore" },
- {16,7,"modules" },
- {17,4,"stat" },
- };
-
- #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0])))
-
- static int proc_lookuproot(struct inode * dir,const char * name, int len,
- struct inode ** result)
- {
- unsigned int pid, c;
- int i, ino;
-
- *result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- i = NR_ROOT_DIRENTRY;
- while (i-- > 0 && !proc_match(len,name,root_dir+i))
- /* nothing */;
- if (i >= 0) {
- ino = root_dir[i].low_ino;
- if (ino == 1) {
- *result = dir;
- return 0;
- }
- if (ino == 7) /* self modifying inode ... */
- ino = (current->pid << 16) + 2;
- } else {
- pid = 0;
- while (len-- > 0) {
- c = *name - '0';
- name++;
- if (c > 9) {
- pid = 0;
- break;
- }
- pid *= 10;
- pid += c;
- if (pid & 0xffff0000) {
- pid = 0;
- break;
- }
- }
- for (i = 0 ; i < NR_TASKS ; i++)
- if (task[i] && task[i]->pid == pid)
- break;
- if (!pid || i >= NR_TASKS) {
- iput(dir);
- return -ENOENT;
- }
- ino = (pid << 16) + 2;
- }
- if (!(*result = iget(dir->i_sb,ino))) {
- iput(dir);
- return -ENOENT;
- }
- iput(dir);
- return 0;
- }
-
- static int proc_readroot(struct inode * inode, struct file * filp,
- struct dirent * dirent, int count)
- {
- struct task_struct * p;
- unsigned int nr,pid;
- int i,j;
-
- if (!inode || !S_ISDIR(inode->i_mode))
- return -EBADF;
- repeat:
- nr = filp->f_pos;
- if (nr < NR_ROOT_DIRENTRY) {
- struct proc_dir_entry * de = root_dir + nr;
-
- filp->f_pos++;
- i = de->namelen;
- put_fs_long(de->low_ino, &dirent->d_ino);
- put_fs_word(i,&dirent->d_reclen);
- put_fs_byte(0,i+dirent->d_name);
- j = i;
- while (i--)
- put_fs_byte(de->name[i], i+dirent->d_name);
- return j;
- }
- nr -= NR_ROOT_DIRENTRY;
- if (nr >= NR_TASKS)
- return 0;
- filp->f_pos++;
- p = task[nr];
- if (!p || !(pid = p->pid))
- goto repeat;
- if (pid & 0xffff0000)
- goto repeat;
- j = 10;
- i = 1;
- while (pid >= j) {
- j *= 10;
- i++;
- }
- j = i;
- put_fs_long((pid << 16)+2, &dirent->d_ino);
- put_fs_word(i, &dirent->d_reclen);
- put_fs_byte(0, i+dirent->d_name);
- while (i--) {
- put_fs_byte('0'+(pid % 10), i+dirent->d_name);
- pid /= 10;
- }
- return j;
- }
-