Linux-2.4.0-test2
[davej-history.git] / fs / devpts / root.c
blob06f6b3baa2ee577c6dec60fbb360e0fdc9d3322d
1 /* -*- linux-c -*- --------------------------------------------------------- *
3 * linux/fs/devpts/root.c
5 * Copyright 1998 H. Peter Anvin -- All Rights Reserved
7 * This file is part of the Linux kernel and is made available under
8 * the terms of the GNU General Public License, version 2, or at your
9 * option, any later version, incorporated herein by reference.
11 * ------------------------------------------------------------------------- */
13 #include <linux/errno.h>
14 #include <linux/stat.h>
15 #include <linux/param.h>
16 #include <linux/string.h>
17 #include "devpts_i.h"
19 static int devpts_root_readdir(struct file *,void *,filldir_t);
20 static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
21 static int devpts_revalidate(struct dentry *, int);
23 struct file_operations devpts_root_operations = {
24 read: generic_read_dir,
25 readdir: devpts_root_readdir,
28 struct inode_operations devpts_root_inode_operations = {
29 lookup: devpts_root_lookup,
32 static struct dentry_operations devpts_dentry_operations = {
33 d_revalidate: devpts_revalidate,
37 * The normal naming convention is simply /dev/pts/<number>; this conforms
38 * to the System V naming convention
41 #define genptsname(buf,num) sprintf(buf, "%d", num)
43 static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
45 struct inode * inode = filp->f_dentry->d_inode;
46 struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
47 off_t nr;
48 char numbuf[16];
50 nr = filp->f_pos;
52 switch(nr)
54 case 0:
55 if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
56 return 0;
57 filp->f_pos = ++nr;
58 /* fall through */
59 case 1:
60 if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
61 return 0;
62 filp->f_pos = ++nr;
63 /* fall through */
64 default:
65 while ( nr - 2 < sbi->max_ptys ) {
66 int ptynr = nr - 2;
67 if ( sbi->inodes[ptynr] ) {
68 genptsname(numbuf, ptynr);
69 if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
70 return 0;
72 filp->f_pos = ++nr;
74 break;
77 return 0;
81 * Revalidate is called on every cache lookup. We use it to check that
82 * the pty really does still exist. Never revalidate negative dentries;
83 * for simplicity (fix later?)
85 static int devpts_revalidate(struct dentry * dentry, int flags)
87 struct devpts_sb_info *sbi;
89 if ( !dentry->d_inode )
90 return 0;
92 sbi = SBI(dentry->d_inode->i_sb);
94 return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
97 static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * dentry)
99 struct devpts_sb_info *sbi = SBI(dir->i_sb);
100 unsigned int entry;
101 int i;
102 const char *p;
104 dentry->d_inode = NULL; /* Assume failure */
105 dentry->d_op = &devpts_dentry_operations;
107 if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
108 entry = 0;
109 } else if ( dentry->d_name.len < 1 ) {
110 return NULL;
111 } else {
112 p = dentry->d_name.name;
113 if ( *p < '1' || *p > '9' )
114 return NULL;
115 entry = *p++ - '0';
117 for ( i = dentry->d_name.len-1 ; i ; i-- ) {
118 unsigned int nentry = *p++ - '0';
119 if ( nentry > 9 )
120 return NULL;
121 if ( entry >= ~0U/10 )
122 return NULL;
123 entry = nentry + entry * 10;
127 if ( entry >= sbi->max_ptys )
128 return NULL;
130 dentry->d_inode = sbi->inodes[entry];
131 if ( dentry->d_inode )
132 atomic_inc(&dentry->d_inode->i_count);
134 d_add(dentry, dentry->d_inode);
136 return NULL;