1 /* -*- linux-c -*- --------------------------------------------------------- *
3 * linux/fs/devpts/inode.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/module.h>
15 #include <linux/string.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/malloc.h>
23 #include <linux/stat.h>
24 #include <linux/tty.h>
25 #include <asm/bitops.h>
26 #include <asm/uaccess.h>
30 static struct vfsmount
*devpts_mnt
;
32 static void devpts_put_super(struct super_block
*sb
)
34 struct devpts_sb_info
*sbi
= SBI(sb
);
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
));
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
);
54 static struct super_operations devpts_sops
= {
55 put_super
: devpts_put_super
,
56 statfs
: devpts_statfs
,
57 remount_fs
: devpts_remount
,
60 static int devpts_parse_options(char *options
, struct devpts_sb_info
*sbi
)
67 char *this_char
, *value
;
71 this_char
= strtok(options
,",");
72 for ( ; this_char
; this_char
= strtok(NULL
,",")) {
73 if ((value
= strchr(this_char
,'=')) != NULL
)
75 if (!strcmp(this_char
,"uid")) {
76 if (!value
|| !*value
)
78 uid
= simple_strtoul(value
,&value
,0);
83 else if (!strcmp(this_char
,"gid")) {
84 if (!value
|| !*value
)
86 gid
= simple_strtoul(value
,&value
,0);
91 else if (!strcmp(this_char
,"mode")) {
92 if (!value
|| !*value
)
94 mode
= simple_strtoul(value
,&value
,8);
101 sbi
->setuid
= setuid
;
102 sbi
->setgid
= setgid
;
105 sbi
->mode
= mode
& ~S_IFMT
;
110 static int devpts_remount(struct super_block
* sb
, int * flags
, char * data
)
112 struct devpts_sb_info
*sbi
= sb
->u
.generic_sbp
;
113 int res
= devpts_parse_options(data
,sbi
);
115 printk("devpts: called with bogus options\n");
121 struct super_block
*devpts_read_super(struct super_block
*s
, void *data
,
124 struct inode
* inode
;
125 struct devpts_sb_info
*sbi
;
127 sbi
= (struct devpts_sb_info
*) kmalloc(sizeof(struct devpts_sb_info
), GFP_KERNEL
);
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
);
136 memset(sbi
->inodes
, 0, sizeof(struct inode
*) * sbi
->max_ptys
);
138 if ( devpts_parse_options(data
,sbi
) && !silent
) {
139 printk("devpts: called with bogus options\n");
143 inode
= get_empty_inode();
147 inode
->i_dev
= s
->s_dev
;
149 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
152 inode
->i_blksize
= 1024;
153 inode
->i_uid
= inode
->i_gid
= 0;
154 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
| S_IWUSR
;
155 inode
->i_op
= &devpts_root_inode_operations
;
156 inode
->i_fop
= &devpts_root_operations
;
159 s
->u
.generic_sbp
= (void *) sbi
;
160 s
->s_blocksize
= 1024;
161 s
->s_blocksize_bits
= 10;
162 s
->s_magic
= DEVPTS_SUPER_MAGIC
;
163 s
->s_op
= &devpts_sops
;
164 s
->s_root
= d_alloc_root(inode
);
168 printk("devpts: get root dentry failed\n");
176 static int devpts_statfs(struct super_block
*sb
, struct statfs
*buf
)
178 buf
->f_type
= DEVPTS_SUPER_MAGIC
;
180 buf
->f_namelen
= NAME_MAX
;
184 static DECLARE_FSTYPE(devpts_fs_type
, "devpts", devpts_read_super
, FS_SINGLE
);
186 void devpts_pty_new(int number
, kdev_t device
)
188 struct super_block
*sb
= devpts_mnt
->mnt_sb
;
189 struct devpts_sb_info
*sbi
= SBI(sb
);
192 if ( sbi
->inodes
[number
] )
193 return; /* Already registered, this does happen */
195 inode
= get_empty_inode();
199 inode
->i_dev
= sb
->s_dev
;
200 inode
->i_ino
= number
+2;
202 inode
->i_blksize
= 1024;
203 inode
->i_uid
= sbi
->setuid
? sbi
->uid
: current
->fsuid
;
204 inode
->i_gid
= sbi
->setgid
? sbi
->gid
: current
->fsgid
;
205 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
206 init_special_inode(inode
, S_IFCHR
|sbi
->mode
, kdev_t_to_nr(device
));
208 if ( sbi
->inodes
[number
] ) {
212 sbi
->inodes
[number
] = inode
;
215 void devpts_pty_kill(int number
)
217 struct super_block
*sb
= devpts_mnt
->mnt_sb
;
218 struct devpts_sb_info
*sbi
= SBI(sb
);
219 struct inode
*inode
= sbi
->inodes
[number
];
222 sbi
->inodes
[number
] = NULL
;
228 int __init
init_devpts_fs(void)
230 int err
= register_filesystem(&devpts_fs_type
);
232 devpts_mnt
= kern_mount(&devpts_fs_type
);
233 err
= PTR_ERR(devpts_mnt
);
234 if (!IS_ERR(devpts_mnt
))
242 int init_module(void)
244 int err
= init_devpts_fs();
246 devpts_upcall_new
= devpts_pty_new
;
247 devpts_upcall_kill
= devpts_pty_kill
;
252 void cleanup_module(void)
254 devpts_upcall_new
= NULL
;
255 devpts_upcall_kill
= NULL
;
256 unregister_filesystem(&devpts_fs_type
);
257 kern_umount(devpts_mnt
);