58217f5900
WOO HOO!
179 lines
3.6 KiB
C
179 lines
3.6 KiB
C
/*
|
|
* 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;
|
|
}
|