File: /usr/src/linux/drivers/isdn/avmb1/capifs.c

1     /*
2      * $Id: capifs.c,v 1.14.6.7 2001/05/24 08:29:08 kai Exp $
3      * 
4      * (c) Copyright 2000 by Carsten Paeth (calle@calle.de)
5      *
6      * Heavily based on devpts filesystem from H. Peter Anvin
7      * 
8      */
9     
10     #include <linux/version.h>
11     #include <linux/fs.h>
12     #include <linux/tty.h>
13     #include <linux/types.h>
14     #include <linux/errno.h>
15     #include <linux/stat.h>
16     #include <linux/param.h>
17     #include <linux/module.h>
18     #include <linux/string.h>
19     #include <linux/init.h>
20     #include <linux/kdev_t.h>
21     #include <linux/kernel.h>
22     #include <linux/locks.h>
23     #include <linux/major.h>
24     #include <linux/slab.h>
25     #include <linux/ctype.h>
26     #include <asm/bitops.h>
27     #include <asm/uaccess.h>
28     
29     MODULE_AUTHOR("Carsten Paeth <calle@calle.de>");
30     
31     static char *revision = "$Revision: 1.14.6.7 $";
32     
33     struct capifs_ncci {
34     	struct inode *inode;
35     	char used;
36     	char type;
37     	unsigned int num;
38     	kdev_t kdev;
39     };
40     
41     struct capifs_sb_info {
42     	u32 magic;
43     	struct super_block *next;
44     	struct super_block **back;
45     	int setuid;
46     	int setgid;
47     	uid_t   uid;
48     	gid_t   gid;
49     	umode_t mode;
50     
51     	unsigned int max_ncci;
52     	struct capifs_ncci *nccis;
53     };
54     
55     #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N')
56     #define CAPIFS_SBI_MAGIC   (('C'<<24)|('A'<<16)|('P'<<8)|'I')
57     
58     static inline struct capifs_sb_info *SBI(struct super_block *sb)
59     {
60     	return (struct capifs_sb_info *)(sb->u.generic_sbp);
61     }
62     
63     /* ------------------------------------------------------------------ */
64     
65     static int capifs_root_readdir(struct file *,void *,filldir_t);
66     static struct dentry *capifs_root_lookup(struct inode *,struct dentry *);
67     static int capifs_revalidate(struct dentry *, int);
68     static struct inode *capifs_new_inode(struct super_block *sb);
69     
70     static struct file_operations capifs_root_operations = {
71     	read:		generic_read_dir,
72     	readdir:	capifs_root_readdir,
73     };
74     
75     struct inode_operations capifs_root_inode_operations = {
76     	lookup: capifs_root_lookup,
77     };
78     
79     static struct dentry_operations capifs_dentry_operations = {
80     	d_revalidate: capifs_revalidate,
81     };
82     
83     /*
84      * /dev/capi/%d
85      * /dev/capi/r%d
86      */
87     
88     static int capifs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
89     {
90     	struct inode * inode = filp->f_dentry->d_inode;
91     	struct capifs_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
92     	off_t nr;
93     	char numbuf[32];
94     
95     	nr = filp->f_pos;
96     
97     	switch(nr)
98     	{
99     	case 0:
100     		if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
101     			return 0;
102     		filp->f_pos = ++nr;
103     		/* fall through */
104     	case 1:
105     		if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
106     			return 0;
107     		filp->f_pos = ++nr;
108     		/* fall through */
109     	default:
110     		while (nr < sbi->max_ncci) {
111     			int n = nr - 2;
112     			struct capifs_ncci *np = &sbi->nccis[n];
113     			if (np->inode && np->used) {
114     				char *p = numbuf;
115     				if (np->type) *p++ = np->type;
116     				sprintf(p, "%u", np->num);
117     				if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_UNKNOWN) < 0 )
118     					return 0;
119     			}
120     			filp->f_pos = ++nr;
121     		}
122     		break;
123     	}
124     
125     	return 0;
126     }
127     
128     /*
129      * Revalidate is called on every cache lookup.  We use it to check that
130      * the ncci really does still exist.  Never revalidate negative dentries;
131      * for simplicity (fix later?)
132      */
133     static int capifs_revalidate(struct dentry * dentry, int flags)
134     {
135     	struct capifs_sb_info *sbi;
136     
137     	if ( !dentry->d_inode )
138     		return 0;
139     
140     	sbi = SBI(dentry->d_inode->i_sb);
141     
142     	return ( sbi->nccis[dentry->d_inode->i_ino - 2].inode == dentry->d_inode );
143     }
144     
145     static struct dentry *capifs_root_lookup(struct inode * dir, struct dentry * dentry)
146     {
147     	struct capifs_sb_info *sbi = SBI(dir->i_sb);
148     	struct capifs_ncci *np;
149     	unsigned int i;
150     	char numbuf[32];
151     	char *p, *tmp;
152     	unsigned int num;
153     	char type = 0;
154     
155     	dentry->d_inode = NULL;	/* Assume failure */
156     	dentry->d_op    = &capifs_dentry_operations;
157     
158     	if (dentry->d_name.len >= sizeof(numbuf) )
159     		return NULL;
160     	strncpy(numbuf, dentry->d_name.name, dentry->d_name.len);
161     	numbuf[dentry->d_name.len] = 0;
162             p = numbuf;
163     	if (!isdigit(*p)) type = *p++;
164     	tmp = p;
165     	num = (unsigned int)simple_strtoul(p, &tmp, 10);
166     	if (tmp == p || *tmp)
167     		return NULL;
168     
169     	for (i = 0, np = sbi->nccis ; i < sbi->max_ncci; i++, np++) {
170     		if (np->used && np->num == num && np->type == type)
171     			break;
172     	}
173     
174     	if ( i >= sbi->max_ncci )
175     		return NULL;
176     
177     	dentry->d_inode = np->inode;
178     	if ( dentry->d_inode )
179     		atomic_inc(&dentry->d_inode->i_count);
180     	
181     	d_add(dentry, dentry->d_inode);
182     
183     	return NULL;
184     }
185     
186     /* ------------------------------------------------------------------ */
187     
188     static struct super_block *mounts = NULL;
189     
190     static void capifs_put_super(struct super_block *sb)
191     {
192     	struct capifs_sb_info *sbi = SBI(sb);
193     	struct inode *inode;
194     	int i;
195     
196     	for ( i = 0 ; i < sbi->max_ncci ; i++ ) {
197     		if ( (inode = sbi->nccis[i].inode) ) {
198     			if (atomic_read(&inode->i_count) != 1 )
199     				printk("capifs_put_super: badness: entry %d count %d\n",
200     				       i, (unsigned)atomic_read(&inode->i_count));
201     			inode->i_nlink--;
202     			iput(inode);
203     		}
204     	}
205     
206     	*sbi->back = sbi->next;
207     	if ( sbi->next )
208     		SBI(sbi->next)->back = sbi->back;
209     
210     	kfree(sbi->nccis);
211     	kfree(sbi);
212     }
213     
214     static int capifs_statfs(struct super_block *sb, struct statfs *buf);
215     
216     static struct super_operations capifs_sops = {
217     	put_super:	capifs_put_super,
218     	statfs:		capifs_statfs,
219     };
220     
221     static int capifs_parse_options(char *options, struct capifs_sb_info *sbi)
222     {
223     	int setuid = 0;
224     	int setgid = 0;
225     	uid_t uid = 0;
226     	gid_t gid = 0;
227     	umode_t mode = 0600;
228     	unsigned int maxncci = 512;
229     	char *this_char, *value;
230     
231     	this_char = NULL;
232     	if ( options )
233     		this_char = strtok(options,",");
234     	for ( ; this_char; this_char = strtok(NULL,",")) {
235     		if ((value = strchr(this_char,'=')) != NULL)
236     			*value++ = 0;
237     		if (!strcmp(this_char,"uid")) {
238     			if (!value || !*value)
239     				return 1;
240     			uid = simple_strtoul(value,&value,0);
241     			if (*value)
242     				return 1;
243     			setuid = 1;
244     		}
245     		else if (!strcmp(this_char,"gid")) {
246     			if (!value || !*value)
247     				return 1;
248     			gid = simple_strtoul(value,&value,0);
249     			if (*value)
250     				return 1;
251     			setgid = 1;
252     		}
253     		else if (!strcmp(this_char,"mode")) {
254     			if (!value || !*value)
255     				return 1;
256     			mode = simple_strtoul(value,&value,8);
257     			if (*value)
258     				return 1;
259     		}
260     		else if (!strcmp(this_char,"maxncci")) {
261     			if (!value || !*value)
262     				return 1;
263     			maxncci = simple_strtoul(value,&value,8);
264     			if (*value)
265     				return 1;
266     		}
267     		else
268     			return 1;
269     	}
270     	sbi->setuid   = setuid;
271     	sbi->setgid   = setgid;
272     	sbi->uid      = uid;
273     	sbi->gid      = gid;
274     	sbi->mode     = mode & ~S_IFMT;
275     	sbi->max_ncci = maxncci;
276     
277     	return 0;
278     }
279     
280     struct super_block *capifs_read_super(struct super_block *s, void *data,
281     				      int silent)
282     {
283     	struct inode * root_inode;
284     	struct dentry * root;
285     	struct capifs_sb_info *sbi;
286     
287     	/* Super block already completed? */
288     	if (s->s_root)
289     		goto out;
290     
291     	sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
292     	if ( !sbi )
293     		goto fail;
294     
295     	memset(sbi, 0, sizeof(struct capifs_sb_info));
296     	sbi->magic  = CAPIFS_SBI_MAGIC;
297     
298     	if ( capifs_parse_options(data,sbi) ) {
299     		kfree(sbi);
300     		printk("capifs: called with bogus options\n");
301     		goto fail;
302     	}
303     
304     	sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL);
305     	if ( !sbi->nccis ) {
306     		kfree(sbi);
307     		goto fail;
308     	}
309     	memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci);
310     
311     	s->u.generic_sbp = (void *) sbi;
312     	s->s_blocksize = 1024;
313     	s->s_blocksize_bits = 10;
314     	s->s_magic = CAPIFS_SUPER_MAGIC;
315     	s->s_op = &capifs_sops;
316     	s->s_root = NULL;
317     
318     	/*
319     	 * Get the root inode and dentry, but defer checking for errors.
320     	 */
321     	root_inode = capifs_new_inode(s);
322     	if (root_inode) {
323     		root_inode->i_ino = 1;
324     		root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
325     		root_inode->i_op = &capifs_root_inode_operations;
326     		root_inode->i_fop = &capifs_root_operations;
327     		root_inode->i_nlink = 2;
328     	} 
329     	root = d_alloc_root(root_inode);
330     
331     	/*
332     	 * Check whether somebody else completed the super block.
333     	 */
334     	if (s->s_root) {
335     		if (root) dput(root);
336     		else iput(root_inode);
337     		goto out;
338     	}
339     
340     	if (!root) {
341     		printk("capifs: get root dentry failed\n");
342     		/*
343     	 	* iput() can block, so we clear the super block first.
344     	 	*/
345     		iput(root_inode);
346     		kfree(sbi->nccis);
347     		kfree(sbi);
348     		goto fail;
349     	}
350     
351     	/*
352     	 * Check whether somebody else completed the super block.
353     	 */
354     	if (s->s_root)
355     		goto out;
356     	
357     	/*
358     	 * Success! Install the root dentry now to indicate completion.
359     	 */
360     	s->s_root = root;
361     
362     	sbi->next = mounts;
363     	if ( sbi->next )
364     		SBI(sbi->next)->back = &(sbi->next);
365     	sbi->back = &mounts;
366     	mounts = s;
367     
368     out:	/* Success ... somebody else completed the super block for us. */ 
369     	return s;
370     fail:
371     	return NULL;
372     }
373     
374     static int capifs_statfs(struct super_block *sb, struct statfs *buf)
375     {
376     	buf->f_type = CAPIFS_SUPER_MAGIC;
377     	buf->f_bsize = 1024;
378     	buf->f_blocks = 0;
379     	buf->f_bfree = 0;
380     	buf->f_bavail = 0;
381     	buf->f_files = 0;
382     	buf->f_ffree = 0;
383     	buf->f_namelen = NAME_MAX;
384     	return 0;
385     }
386     
387     static struct inode *capifs_new_inode(struct super_block *sb)
388     {
389     	struct inode *inode = new_inode(sb);
390     	if (inode) {
391     		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
392     		inode->i_blocks = 0;
393     		inode->i_blksize = 1024;
394     		inode->i_uid = inode->i_gid = 0;
395     	}
396     	return inode;
397     }
398     
399     static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
400     
401     void capifs_new_ncci(char type, unsigned int num, kdev_t device)
402     {
403     	struct super_block *sb;
404     	struct capifs_sb_info *sbi;
405     	struct capifs_ncci *np;
406     	ino_t ino;
407     
408     	for ( sb = mounts ; sb ; sb = sbi->next ) {
409     		sbi = SBI(sb);
410     
411     		for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) {
412     			if (np->used == 0) {
413     				np->used = 1;
414     				np->type = type;
415     				np->num = num;
416     				np->kdev = device;
417     				break;
418     			}
419     		}
420     		if ( ino >= sbi->max_ncci )
421     			continue;
422     
423     		if ((np->inode = capifs_new_inode(sb)) != NULL) {
424     			struct inode *inode = np->inode;
425     			inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
426     			inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
427     			inode->i_nlink = 1;
428     			inode->i_ino = ino + 2;
429     			init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
430     		}
431     	}
432     }
433     
434     void capifs_free_ncci(char type, unsigned int num)
435     {
436     	struct super_block *sb;
437     	struct capifs_sb_info *sbi;
438     	struct inode *inode;
439     	struct capifs_ncci *np;
440     	ino_t ino;
441     
442     	for ( sb = mounts ; sb ; sb = sbi->next ) {
443     		sbi = SBI(sb);
444     
445     		for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) {
446     			if (!np->used || np->type != type || np->num != num)
447     				continue;
448     			if (np->inode) {
449     				inode = np->inode;
450     				np->inode = 0;
451     				np->used = 0;
452     				inode->i_nlink--;
453     				iput(inode);
454     				break;
455     			}
456     		}
457     	}
458     }
459     
460     static int __init capifs_init(void)
461     {
462     	char rev[32];
463     	char *p;
464     	int err;
465     
466     	MOD_INC_USE_COUNT;
467     
468     	if ((p = strchr(revision, ':')) != 0 && p[1]) {
469     		strncpy(rev, p + 2, sizeof(rev));
470     		rev[sizeof(rev)-1] = 0;
471     		if ((p = strchr(rev, '$')) != 0 && p > rev)
472     		   *(p-1) = 0;
473     	} else
474     		strcpy(rev, "1.0");
475     
476     	err = register_filesystem(&capifs_fs_type);
477     	if (err) {
478     		MOD_DEC_USE_COUNT;
479     		return err;
480     	}
481             printk(KERN_NOTICE "capifs: Rev %s\n", rev);
482     	MOD_DEC_USE_COUNT;
483     	return 0;
484     }
485     
486     static void __exit capifs_exit(void)
487     {
488     	unregister_filesystem(&capifs_fs_type);
489     }
490     
491     EXPORT_SYMBOL(capifs_new_ncci);
492     EXPORT_SYMBOL(capifs_free_ncci);
493     
494     module_init(capifs_init);
495     module_exit(capifs_exit);
496