File: /usr/src/linux/fs/devpts/inode.c

1     /* -*- linux-c -*- --------------------------------------------------------- *
2      *
3      * linux/fs/devpts/inode.c
4      *
5      *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
6      *
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.
10      *
11      * ------------------------------------------------------------------------- */
12     
13     #include <linux/module.h>
14     
15     #include <linux/string.h>
16     #include <linux/fs.h>
17     #include <linux/init.h>
18     #include <linux/kdev_t.h>
19     #include <linux/kernel.h>
20     #include <linux/locks.h>
21     #include <linux/major.h>
22     #include <linux/slab.h>
23     #include <linux/stat.h>
24     #include <linux/tty.h>
25     #include <asm/bitops.h>
26     #include <asm/uaccess.h>
27     
28     #include "devpts_i.h"
29     
30     static struct vfsmount *devpts_mnt;
31     
32     static void devpts_put_super(struct super_block *sb)
33     {
34     	struct devpts_sb_info *sbi = SBI(sb);
35     	struct inode *inode;
36     	int i;
37     
38     	for ( i = 0 ; i < sbi->max_ptys ; i++ ) {
39     		if ( (inode = sbi->inodes[i]) ) {
40     			if ( atomic_read(&inode->i_count) != 1 )
41     				printk("devpts_put_super: badness: entry %d count %d\n",
42     				       i, atomic_read(&inode->i_count));
43     			inode->i_nlink--;
44     			iput(inode);
45     		}
46     	}
47     	kfree(sbi->inodes);
48     	kfree(sbi);
49     }
50     
51     static int devpts_statfs(struct super_block *sb, struct statfs *buf);
52     static int devpts_remount (struct super_block * sb, int * flags, char * data);
53     
54     static struct super_operations devpts_sops = {
55     	put_super:	devpts_put_super,
56     	statfs:		devpts_statfs,
57     	remount_fs:	devpts_remount,
58     };
59     
60     static int devpts_parse_options(char *options, struct devpts_sb_info *sbi)
61     {
62     	int setuid = 0;
63     	int setgid = 0;
64     	uid_t uid = 0;
65     	gid_t gid = 0;
66     	umode_t mode = 0600;
67     	char *this_char, *value;
68     
69     	this_char = NULL;
70     	if ( options )
71     		this_char = strtok(options,",");
72     	for ( ; this_char; this_char = strtok(NULL,",")) {
73     		if ((value = strchr(this_char,'=')) != NULL)
74     			*value++ = 0;
75     		if (!strcmp(this_char,"uid")) {
76     			if (!value || !*value)
77     				return 1;
78     			uid = simple_strtoul(value,&value,0);
79     			if (*value)
80     				return 1;
81     			setuid = 1;
82     		}
83     		else if (!strcmp(this_char,"gid")) {
84     			if (!value || !*value)
85     				return 1;
86     			gid = simple_strtoul(value,&value,0);
87     			if (*value)
88     				return 1;
89     			setgid = 1;
90     		}
91     		else if (!strcmp(this_char,"mode")) {
92     			if (!value || !*value)
93     				return 1;
94     			mode = simple_strtoul(value,&value,8);
95     			if (*value)
96     				return 1;
97     		}
98     		else
99     			return 1;
100     	}
101     	sbi->setuid  = setuid;
102     	sbi->setgid  = setgid;
103     	sbi->uid     = uid;
104     	sbi->gid     = gid;
105     	sbi->mode    = mode & ~S_IFMT;
106     
107     	return 0;
108     }
109     
110     static int devpts_remount(struct super_block * sb, int * flags, char * data)
111     {
112     	struct devpts_sb_info *sbi = sb->u.generic_sbp;
113     	int res = devpts_parse_options(data,sbi);
114     	if (res) {
115     		printk("devpts: called with bogus options\n");
116     		return -EINVAL;
117     	}
118     	return 0;
119     }
120     
121     struct super_block *devpts_read_super(struct super_block *s, void *data,
122     				      int silent)
123     {
124     	struct inode * inode;
125     	struct devpts_sb_info *sbi;
126     
127     	sbi = (struct devpts_sb_info *) kmalloc(sizeof(struct devpts_sb_info), GFP_KERNEL);
128     	if ( !sbi )
129     		goto fail;
130     
131     	sbi->magic  = DEVPTS_SBI_MAGIC;
132     	sbi->max_ptys = unix98_max_ptys;
133     	sbi->inodes = kmalloc(sizeof(struct inode *) * sbi->max_ptys, GFP_KERNEL);
134     	if ( !sbi->inodes )
135     		goto fail_free;
136     	memset(sbi->inodes, 0, sizeof(struct inode *) * sbi->max_ptys);
137     
138     	if ( devpts_parse_options(data,sbi) && !silent) {
139     		printk("devpts: called with bogus options\n");
140     		goto fail_free;
141     	}
142     
143     	inode = new_inode(s);
144     	if (!inode)
145     		goto fail_free;
146     	inode->i_ino = 1;
147     	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
148     	inode->i_blocks = 0;
149     	inode->i_blksize = 1024;
150     	inode->i_uid = inode->i_gid = 0;
151     	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
152     	inode->i_op = &devpts_root_inode_operations;
153     	inode->i_fop = &devpts_root_operations;
154     	inode->i_nlink = 2;
155     
156     	s->u.generic_sbp = (void *) sbi;
157     	s->s_blocksize = 1024;
158     	s->s_blocksize_bits = 10;
159     	s->s_magic = DEVPTS_SUPER_MAGIC;
160     	s->s_op = &devpts_sops;
161     	s->s_root = d_alloc_root(inode);
162     	if (s->s_root)
163     		return s;
164     	
165     	printk("devpts: get root dentry failed\n");
166     	iput(inode);
167     fail_free:
168     	kfree(sbi);
169     fail:
170     	return NULL;
171     }
172     
173     static int devpts_statfs(struct super_block *sb, struct statfs *buf)
174     {
175     	buf->f_type = DEVPTS_SUPER_MAGIC;
176     	buf->f_bsize = 1024;
177     	buf->f_namelen = NAME_MAX;
178     	return 0;
179     }
180     
181     static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, FS_SINGLE);
182     
183     void devpts_pty_new(int number, kdev_t device)
184     {
185     	struct super_block *sb = devpts_mnt->mnt_sb;
186     	struct devpts_sb_info *sbi = SBI(sb);
187     	struct inode *inode;
188     		
189     	if ( sbi->inodes[number] )
190     		return; /* Already registered, this does happen */
191     		
192     	inode = new_inode(sb);
193     	if (!inode)
194     		return;
195     	inode->i_ino = number+2;
196     	inode->i_blocks = 0;
197     	inode->i_blksize = 1024;
198     	inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
199     	inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
200     	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
201     	init_special_inode(inode, S_IFCHR|sbi->mode, kdev_t_to_nr(device));
202     
203     	if ( sbi->inodes[number] ) {
204     		iput(inode);
205     		return;
206     	}
207     	sbi->inodes[number] = inode;
208     }
209     
210     void devpts_pty_kill(int number)
211     {
212     	struct super_block *sb = devpts_mnt->mnt_sb;
213     	struct devpts_sb_info *sbi = SBI(sb);
214     	struct inode *inode = sbi->inodes[number];
215     
216     	if ( inode ) {
217     		sbi->inodes[number] = NULL;
218     		inode->i_nlink--;
219     		iput(inode);
220     	}
221     }
222     
223     static int __init init_devpts_fs(void)
224     {
225     	int err = register_filesystem(&devpts_fs_type);
226     	if (!err) {
227     		devpts_mnt = kern_mount(&devpts_fs_type);
228     		err = PTR_ERR(devpts_mnt);
229     		if (!IS_ERR(devpts_mnt))
230     			err = 0;
231     #ifdef MODULE
232     		if ( !err ) {
233     			devpts_upcall_new  = devpts_pty_new;
234     			devpts_upcall_kill = devpts_pty_kill;
235     		}
236     #endif
237     	}
238     	return err;
239     }
240     
241     static void __exit exit_devpts_fs(void)
242     {
243     #ifdef MODULE
244     	devpts_upcall_new  = NULL;
245     	devpts_upcall_kill = NULL;
246     #endif
247     	unregister_filesystem(&devpts_fs_type);
248     	kern_umount(devpts_mnt);
249     }
250     
251     module_init(init_devpts_fs)
252     module_exit(exit_devpts_fs)
253