capifs.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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