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>
16 #include <linux/init.h>
17 #include <linux/kdev_t.h>
18 #include <linux/kernel.h>
19 #include <linux/locks.h>
20 #include <linux/major.h>
21 #include <linux/malloc.h>
22 #include <linux/stat.h>
23 #include <linux/tty.h>
24 #include <asm/bitops.h>
25 #include <asm/uaccess.h>
29 static struct super_block
*mounts
= NULL
;
31 static void devpts_put_super(struct super_block
*sb
)
33 struct devpts_sb_info
*sbi
= SBI(sb
);
37 for ( i
= 0 ; i
< NR_PTYS
; i
++ ) {
38 if ( (inode
= sbi
->inodes
[i
]) ) {
39 if ( inode
->i_count
!= 1 )
40 printk("devpts_put_super: badness: entry %d count %d\n",
47 *sbi
->back
= sbi
->next
;
49 SBI(sbi
->next
)->back
= sbi
->back
;
58 static int devpts_statfs(struct super_block
*sb
, struct statfs
*buf
, int bufsiz
);
59 static void devpts_read_inode(struct inode
*inode
);
60 static void devpts_write_inode(struct inode
*inode
);
62 static struct super_operations devpts_sops
= {
66 NULL
, /* delete_inode */
67 NULL
, /* notify_change */
69 NULL
, /* write_super */
71 NULL
, /* remount_fs */
72 NULL
, /* clear_inode */
75 static int devpts_parse_options(char *options
, struct devpts_sb_info
*sbi
)
79 uid_t uid
= 0; /* To shut up gcc */
82 char *this_char
, *value
;
84 if ( !options
) return 1;
85 for (this_char
= strtok(options
,","); this_char
; this_char
= strtok(NULL
,",")) {
86 if ((value
= strchr(this_char
,'=')) != NULL
)
88 if (!strcmp(this_char
,"uid")) {
89 if (!value
|| !*value
)
91 uid
= simple_strtoul(value
,&value
,0);
96 else if (!strcmp(this_char
,"gid")) {
97 if (!value
|| !*value
)
99 gid
= simple_strtoul(value
,&value
,0);
104 else if (!strcmp(this_char
,"mode")) {
105 if (!value
|| !*value
)
107 mode
= simple_strtoul(value
,&value
,8);
114 sbi
->setuid
= setuid
;
115 sbi
->setgid
= setgid
;
118 sbi
->mode
= mode
& ~S_IFMT
;
123 struct super_block
*devpts_read_super(struct super_block
*s
, void *data
,
126 struct inode
* root_inode
;
127 struct dentry
* root
;
128 struct devpts_sb_info
*sbi
;
133 /* Super block already completed? */
137 sbi
= (struct devpts_sb_info
*) kmalloc(sizeof(struct devpts_sb_info
), GFP_KERNEL
);
141 sbi
->magic
= DEVPTS_SBI_MAGIC
;
142 memset(sbi
->inodes
, 0, sizeof sbi
->inodes
);
144 s
->u
.generic_sbp
= (void *) sbi
;
145 s
->s_blocksize
= 1024;
146 s
->s_blocksize_bits
= 10;
147 s
->s_magic
= DEVPTS_SUPER_MAGIC
;
148 s
->s_op
= &devpts_sops
;
150 unlock_super(s
); /* shouldn't we keep it locked a while longer? */
153 * Get the root inode and dentry, but defer checking for errors.
155 root_inode
= iget(s
, 1); /* inode 1 == root directory */
156 root
= d_alloc_root(root_inode
, NULL
);
159 * Check whether somebody else completed the super block.
167 /* Can this call block? (It shouldn't) */
168 if ( devpts_parse_options(data
,sbi
) ) {
169 printk("devpts: called with bogus options\n");
174 * Check whether somebody else completed the super block.
180 * Success! Install the root dentry now to indicate completion.
187 SBI(sbi
->next
)->back
= &(sbi
->next
);
195 * Success ... somebody else completed the super block for us.
210 * Failure ... clear the s_dev slot and clean up.
214 * dput() can block, so we clear the super block first.
220 printk("devpts: get root dentry failed\n");
222 * iput() can block, so we clear the super block first.
237 static int devpts_statfs(struct super_block
*sb
, struct statfs
*buf
, int bufsiz
)
241 tmp
.f_type
= DEVPTS_SUPER_MAGIC
;
248 tmp
.f_namelen
= NAME_MAX
;
249 return copy_to_user(buf
, &tmp
, bufsiz
) ? -EFAULT
: 0;
252 static void devpts_read_inode(struct inode
*inode
)
254 ino_t ino
= inode
->i_ino
;
260 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
262 inode
->i_blksize
= 1024;
263 inode
->i_uid
= inode
->i_gid
= 0;
266 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
| S_IWUSR
;
267 inode
->i_op
= &devpts_root_inode_operations
;
273 if ( ino
>= NR_PTYS
)
276 inode
->i_mode
= S_IFCHR
;
277 inode
->i_rdev
= MKDEV(0,0); /* Gets filled in by devpts_pty_new() */
279 inode
->i_op
= &chrdev_inode_operations
;
284 static void devpts_write_inode(struct inode
*inode
)
288 static struct file_system_type devpts_fs_type
= {
295 void devpts_pty_new(int number
, kdev_t device
)
297 struct super_block
*sb
;
298 struct devpts_sb_info
*sbi
;
301 for ( sb
= mounts
; sb
; sb
= sbi
->next
) {
304 if ( sbi
->inodes
[number
] ) {
305 continue; /* Already registered, this does happen */
308 /* Yes, this looks backwards, but it is correct */
309 inode
= iget(sb
, number
+2);
311 inode
->i_uid
= sbi
->setuid
? sbi
->uid
: current
->fsuid
;
312 inode
->i_gid
= sbi
->setgid
? sbi
->gid
: current
->fsgid
;
313 inode
->i_mode
= sbi
->mode
| S_IFCHR
;
314 inode
->i_rdev
= device
;
316 sbi
->inodes
[number
] = inode
;
321 void devpts_pty_kill(int number
)
323 struct super_block
*sb
;
324 struct devpts_sb_info
*sbi
;
327 for ( sb
= mounts
; sb
; sb
= sbi
->next
) {
330 inode
= sbi
->inodes
[number
];
333 sbi
->inodes
[number
] = NULL
;
340 __initfunc(int init_devpts_fs(void))
342 return register_filesystem(&devpts_fs_type
);
348 int init_module(void)
350 int err
= init_devpts_fs();
352 devpts_upcall_new
= devpts_pty_new
;
353 devpts_upcall_kill
= devpts_pty_kill
;
358 void cleanup_module(void)
360 devpts_upcall_new
= NULL
;
361 devpts_upcall_kill
= NULL
;
362 unregister_filesystem(&devpts_fs_type
);