• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/isdn/capi/
1/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 Exp $
2 *
3 * Copyright 2000 by Carsten Paeth <calle@calle.de>
4 *
5 * Heavily based on devpts filesystem from H. Peter Anvin
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/fs.h>
13#include <linux/mount.h>
14#include <linux/slab.h>
15#include <linux/namei.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/ctype.h>
19#include <linux/sched.h>	/* current */
20
21#include "capifs.h"
22
23MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
24MODULE_AUTHOR("Carsten Paeth");
25MODULE_LICENSE("GPL");
26
27/* ------------------------------------------------------------------ */
28
29#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
30
31static struct vfsmount *capifs_mnt;
32static int capifs_mnt_count;
33
34static struct {
35	int setuid;
36	int setgid;
37	uid_t   uid;
38	gid_t   gid;
39	umode_t mode;
40} config = {.mode = 0600};
41
42/* ------------------------------------------------------------------ */
43
44static int capifs_remount(struct super_block *s, int *flags, char *data)
45{
46	int setuid = 0;
47	int setgid = 0;
48	uid_t uid = 0;
49	gid_t gid = 0;
50	umode_t mode = 0600;
51	char *this_char;
52	char *new_opt = kstrdup(data, GFP_KERNEL);
53
54	this_char = NULL;
55	while ((this_char = strsep(&data, ",")) != NULL) {
56		int n;
57		char dummy;
58		if (!*this_char)
59			continue;
60		if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
61			setuid = 1;
62			uid = n;
63		} else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
64			setgid = 1;
65			gid = n;
66		} else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
67			mode = n & ~S_IFMT;
68		else {
69			kfree(new_opt);
70			printk("capifs: called with bogus options\n");
71			return -EINVAL;
72		}
73	}
74
75	mutex_lock(&s->s_root->d_inode->i_mutex);
76
77	replace_mount_options(s, new_opt);
78	config.setuid  = setuid;
79	config.setgid  = setgid;
80	config.uid     = uid;
81	config.gid     = gid;
82	config.mode    = mode;
83
84	mutex_unlock(&s->s_root->d_inode->i_mutex);
85
86	return 0;
87}
88
89static const struct super_operations capifs_sops =
90{
91	.statfs		= simple_statfs,
92	.remount_fs	= capifs_remount,
93	.show_options	= generic_show_options,
94};
95
96
97static int
98capifs_fill_super(struct super_block *s, void *data, int silent)
99{
100	struct inode * inode;
101
102	s->s_blocksize = 1024;
103	s->s_blocksize_bits = 10;
104	s->s_magic = CAPIFS_SUPER_MAGIC;
105	s->s_op = &capifs_sops;
106	s->s_time_gran = 1;
107
108	inode = new_inode(s);
109	if (!inode)
110		goto fail;
111	inode->i_ino = 1;
112	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
113	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
114	inode->i_op = &simple_dir_inode_operations;
115	inode->i_fop = &simple_dir_operations;
116	inode->i_nlink = 2;
117
118	s->s_root = d_alloc_root(inode);
119	if (s->s_root)
120		return 0;
121
122	printk("capifs: get root dentry failed\n");
123	iput(inode);
124fail:
125	return -ENOMEM;
126}
127
128static int capifs_get_sb(struct file_system_type *fs_type,
129	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
130{
131	return get_sb_single(fs_type, flags, data, capifs_fill_super, mnt);
132}
133
134static struct file_system_type capifs_fs_type = {
135	.owner		= THIS_MODULE,
136	.name		= "capifs",
137	.get_sb		= capifs_get_sb,
138	.kill_sb	= kill_anon_super,
139};
140
141static struct dentry *new_ncci(unsigned int number, dev_t device)
142{
143	struct super_block *s = capifs_mnt->mnt_sb;
144	struct dentry *root = s->s_root;
145	struct dentry *dentry;
146	struct inode *inode;
147	char name[10];
148	int namelen;
149
150	mutex_lock(&root->d_inode->i_mutex);
151
152	namelen = sprintf(name, "%d", number);
153	dentry = lookup_one_len(name, root, namelen);
154	if (IS_ERR(dentry)) {
155		dentry = NULL;
156		goto unlock_out;
157	}
158
159	if (dentry->d_inode) {
160		dput(dentry);
161		dentry = NULL;
162		goto unlock_out;
163	}
164
165	inode = new_inode(s);
166	if (!inode) {
167		dput(dentry);
168		dentry = NULL;
169		goto unlock_out;
170	}
171
172	/* config contents is protected by root's i_mutex */
173	inode->i_uid = config.setuid ? config.uid : current_fsuid();
174	inode->i_gid = config.setgid ? config.gid : current_fsgid();
175	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
176	inode->i_ino = number + 2;
177	init_special_inode(inode, S_IFCHR|config.mode, device);
178
179	d_instantiate(dentry, inode);
180	dget(dentry);
181
182unlock_out:
183	mutex_unlock(&root->d_inode->i_mutex);
184
185	return dentry;
186}
187
188struct dentry *capifs_new_ncci(unsigned int number, dev_t device)
189{
190	struct dentry *dentry;
191
192	if (simple_pin_fs(&capifs_fs_type, &capifs_mnt, &capifs_mnt_count) < 0)
193		return NULL;
194
195	dentry = new_ncci(number, device);
196	if (!dentry)
197		simple_release_fs(&capifs_mnt, &capifs_mnt_count);
198
199	return dentry;
200}
201
202void capifs_free_ncci(struct dentry *dentry)
203{
204	struct dentry *root = capifs_mnt->mnt_sb->s_root;
205	struct inode *inode;
206
207	if (!dentry)
208		return;
209
210	mutex_lock(&root->d_inode->i_mutex);
211
212	inode = dentry->d_inode;
213	if (inode) {
214		drop_nlink(inode);
215		d_delete(dentry);
216		dput(dentry);
217	}
218	dput(dentry);
219
220	mutex_unlock(&root->d_inode->i_mutex);
221
222	simple_release_fs(&capifs_mnt, &capifs_mnt_count);
223}
224
225static int __init capifs_init(void)
226{
227	return register_filesystem(&capifs_fs_type);
228}
229
230static void __exit capifs_exit(void)
231{
232	unregister_filesystem(&capifs_fs_type);
233}
234
235EXPORT_SYMBOL(capifs_new_ncci);
236EXPORT_SYMBOL(capifs_free_ncci);
237
238module_init(capifs_init);
239module_exit(capifs_exit);
240