Viewing file: root.c (3.24 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* -*- 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; }
|