Import 2.1.118
[davej-history.git] / fs / devpts / root.c
blob04215ad40e9cb9761e6e3775bb5a336f9121bb12
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 int devpts_root_lookup(struct inode *,struct dentry *);
21 static int devpts_revalidate(struct dentry *);
23 static struct file_operations devpts_root_operations = {
24 NULL, /* llseek */
25 NULL, /* read */
26 NULL, /* write */
27 devpts_root_readdir, /* readdir */
28 NULL, /* poll */
29 NULL, /* ioctl */
30 NULL, /* mmap */
31 NULL, /* open */
32 NULL, /* flush */
33 NULL, /* release */
34 NULL, /* fsync */
35 NULL, /* fasync */
36 NULL, /* check_media_change */
37 NULL, /* revalidate */
38 NULL /* lock */
41 struct inode_operations devpts_root_inode_operations = {
42 &devpts_root_operations, /* file operations */
43 NULL, /* create */
44 devpts_root_lookup, /* lookup */
45 NULL, /* link */
46 NULL, /* unlink */
47 NULL, /* symlink */
48 NULL, /* mkdir */
49 NULL, /* rmdir */
50 NULL, /* mknod */
51 NULL, /* rename */
52 NULL, /* readlink */
53 NULL, /* follow_link */
54 NULL, /* readpage */
55 NULL, /* writepage */
56 NULL, /* bmap */
57 NULL, /* truncate */
58 NULL, /* permission */
59 NULL, /* smap */
60 NULL, /* updatepage */
61 NULL /* revalidate */
64 static struct dentry_operations devpts_dentry_operations = {
65 devpts_revalidate, /* d_revalidate */
66 NULL, /* d_hash */
67 NULL, /* d_compare */
71 * The normal naming convention is simply /dev/pts/<number>; this conforms
72 * to the System V naming convention
75 #define genptsname(buf,num) sprintf(buf, "%d", num)
77 static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
79 struct inode * inode = filp->f_dentry->d_inode;
80 struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
81 off_t nr;
82 char numbuf[16];
84 if (!inode || !S_ISDIR(inode->i_mode))
85 return -ENOTDIR;
87 nr = filp->f_pos;
89 switch(nr)
91 case 0:
92 if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
93 return 0;
94 filp->f_pos = ++nr;
95 /* fall through */
96 case 1:
97 if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
98 return 0;
99 filp->f_pos = ++nr;
100 /* fall through */
101 default:
102 while ( nr < sbi->max_ptys ) {
103 int ptynr = nr - 2;
104 if ( sbi->inodes[ptynr] ) {
105 genptsname(numbuf, ptynr);
106 if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
107 return 0;
109 filp->f_pos = ++nr;
111 break;
114 return 0;
118 * Revalidate is called on every cache lookup. We use it to check that
119 * the pty really does still exist. Never revalidate negative dentries;
120 * for simplicity (fix later?)
122 static int devpts_revalidate(struct dentry * dentry)
124 struct devpts_sb_info *sbi;
126 if ( !dentry->d_inode )
127 return 0;
129 sbi = SBI(dentry->d_inode->i_sb);
131 return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
134 static int devpts_root_lookup(struct inode * dir, struct dentry * dentry)
136 struct devpts_sb_info *sbi = SBI(dir->i_sb);
137 int entry, i;
138 const char *p;
140 if (!S_ISDIR(dir->i_mode))
141 return -ENOTDIR;
143 dentry->d_inode = NULL; /* Assume failure */
144 dentry->d_op = &devpts_dentry_operations;
146 if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
147 entry = 0;
148 } else if ( dentry->d_name.len < 1 ) {
149 return 0;
150 } else {
151 p = dentry->d_name.name;
152 if ( *p < '1' || *p > '9' )
153 return 0;
154 entry = *p++ - '0';
156 for ( i = dentry->d_name.len-1 ; i ; i-- ) {
157 if ( *p < '0' || *p > '9' )
158 return 0;
159 entry *= 10;
160 entry += (*p++ - '0');
164 dentry->d_inode = sbi->inodes[entry];
165 if ( dentry->d_inode )
166 dentry->d_inode->i_count++;
168 d_add(dentry, dentry->d_inode);
170 return 0;