root.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:3k
- /* -*- linux-c -*- --------------------------------------------------------- *
- *
- * linux/fs/devpts/root.c
- *
- * Copyright 1998 H. Peter Anvin -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
- #include <linux/errno.h>
- #include <linux/stat.h>
- #include <linux/param.h>
- #include <linux/string.h>
- #include "devpts_i.h"
- static int devpts_root_readdir(struct file *,void *,filldir_t);
- static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
- static int devpts_revalidate(struct dentry *, int);
- struct file_operations devpts_root_operations = {
- read: generic_read_dir,
- readdir: devpts_root_readdir,
- };
- struct inode_operations devpts_root_inode_operations = {
- lookup: devpts_root_lookup,
- };
- static struct dentry_operations devpts_dentry_operations = {
- d_revalidate: devpts_revalidate,
- };
- /*
- * The normal naming convention is simply /dev/pts/<number>; this conforms
- * to the System V naming convention
- */
- #define genptsname(buf,num) sprintf(buf, "%d", num)
- static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
- {
- struct inode * inode = filp->f_dentry->d_inode;
- struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
- off_t nr;
- char numbuf[16];
- nr = filp->f_pos;
- switch(nr)
- {
- case 0:
- if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
- return 0;
- filp->f_pos = ++nr;
- /* fall through */
- case 1:
- if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
- return 0;
- filp->f_pos = ++nr;
- /* fall through */
- default:
- while ( nr - 2 < sbi->max_ptys ) {
- int ptynr = nr - 2;
- if ( sbi->inodes[ptynr] ) {
- genptsname(numbuf, ptynr);
- if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 )
- return 0;
- }
- filp->f_pos = ++nr;
- }
- break;
- }
- return 0;
- }
- /*
- * Revalidate is called on every cache lookup. We use it to check that
- * the pty really does still exist. Never revalidate negative dentries;
- * for simplicity (fix later?)
- */
- static int devpts_revalidate(struct dentry * dentry, int flags)
- {
- struct devpts_sb_info *sbi;
- if ( !dentry->d_inode )
- return 0;
- sbi = SBI(dentry->d_inode->i_sb);
- return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
- }
- static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * dentry)
- {
- struct devpts_sb_info *sbi = SBI(dir->i_sb);
- unsigned int entry;
- int i;
- const char *p;
- dentry->d_op = &devpts_dentry_operations;
- if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
- entry = 0;
- } else if ( dentry->d_name.len < 1 ) {
- return NULL;
- } else {
- p = dentry->d_name.name;
- if ( *p < '1' || *p > '9' )
- return NULL;
- entry = *p++ - '0';
- for ( i = dentry->d_name.len-1 ; i ; i-- ) {
- unsigned int nentry = *p++ - '0';
- if ( nentry > 9 )
- return NULL;
- if ( entry >= ~0U/10 )
- return NULL;
- entry = nentry + entry * 10;
- }
- }
- if ( entry >= sbi->max_ptys )
- return NULL;
- if ( sbi->inodes[entry] )
- atomic_inc(&sbi->inodes[entry]->i_count);
-
- d_add(dentry, sbi->inodes[entry]);
- return NULL;
- }