summaryrefslogtreecommitdiffstats
path: root/fs/proc/root.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1994-11-28 11:59:19 +0000
committer <ralf@linux-mips.org>1994-11-28 11:59:19 +0000
commit1513ff9b7899ab588401c89db0e99903dbf5f886 (patch)
treef69cc81a940a502ea23d664c3ffb2d215a479667 /fs/proc/root.c
Import of Linus's Linux 1.1.68
Diffstat (limited to 'fs/proc/root.c')
-rw-r--r--fs/proc/root.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/fs/proc/root.c b/fs/proc/root.c
new file mode 100644
index 000000000..97cf2ff25
--- /dev/null
+++ b/fs/proc/root.c
@@ -0,0 +1,184 @@
+/*
+ * 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[] = {
+ { PROC_ROOT_INO, 1, "." },
+ { PROC_ROOT_INO, 2, ".." },
+ { PROC_LOADAVG, 7, "loadavg" },
+ { PROC_UPTIME, 6, "uptime" },
+ { PROC_MEMINFO, 7, "meminfo" },
+ { PROC_KMSG, 4, "kmsg" },
+ { PROC_VERSION, 7, "version" },
+ { PROC_SELF, 4, "self" }, /* will change inode # */
+ { PROC_NET, 3, "net" },
+#ifdef CONFIG_DEBUG_MALLOC
+ { PROC_MALLOC, 6, "malloc" },
+#endif
+ { PROC_KCORE, 5, "kcore" },
+ { PROC_MODULES, 7, "modules" },
+ { PROC_STAT, 4, "stat" },
+ { PROC_DEVICES, 7, "devices" },
+ { PROC_INTERRUPTS, 10,"interrupts" },
+ { PROC_FILESYSTEMS, 11,"filesystems" },
+ { PROC_KSYMS, 5, "ksyms" },
+ { PROC_DMA, 3, "dma" },
+};
+
+#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 == PROC_ROOT_INO) {
+ *result = dir;
+ return 0;
+ }
+ if (ino == PROC_SELF) /* 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;
+}