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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- linux-c -*- --------------------------------------------------------- *
  2.  *
  3.  * linux/fs/devpts/root.c
  4.  *
  5.  *  Copyright 1998 H. Peter Anvin -- All Rights Reserved
  6.  *
  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.
  10.  *
  11.  * ------------------------------------------------------------------------- */
  12. #include <linux/errno.h>
  13. #include <linux/stat.h>
  14. #include <linux/param.h>
  15. #include <linux/string.h>
  16. #include "devpts_i.h"
  17. static int devpts_root_readdir(struct file *,void *,filldir_t);
  18. static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
  19. static int devpts_revalidate(struct dentry *, int);
  20. struct file_operations devpts_root_operations = {
  21. read: generic_read_dir,
  22. readdir: devpts_root_readdir,
  23. };
  24. struct inode_operations devpts_root_inode_operations = {
  25. lookup: devpts_root_lookup,
  26. };
  27. static struct dentry_operations devpts_dentry_operations = {
  28. d_revalidate: devpts_revalidate,
  29. };
  30. /*
  31.  * The normal naming convention is simply /dev/pts/<number>; this conforms
  32.  * to the System V naming convention
  33.  */
  34. #define genptsname(buf,num) sprintf(buf, "%d", num)
  35. static int devpts_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
  36. {
  37. struct inode * inode = filp->f_dentry->d_inode;
  38. struct devpts_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb);
  39. off_t nr;
  40. char numbuf[16];
  41. nr = filp->f_pos;
  42. switch(nr)
  43. {
  44. case 0:
  45. if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
  46. return 0;
  47. filp->f_pos = ++nr;
  48. /* fall through */
  49. case 1:
  50. if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
  51. return 0;
  52. filp->f_pos = ++nr;
  53. /* fall through */
  54. default:
  55. while ( nr - 2 < sbi->max_ptys ) {
  56. int ptynr = nr - 2;
  57. if ( sbi->inodes[ptynr] ) {
  58. genptsname(numbuf, ptynr);
  59. if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_CHR) < 0 )
  60. return 0;
  61. }
  62. filp->f_pos = ++nr;
  63. }
  64. break;
  65. }
  66. return 0;
  67. }
  68. /*
  69.  * Revalidate is called on every cache lookup.  We use it to check that
  70.  * the pty really does still exist.  Never revalidate negative dentries;
  71.  * for simplicity (fix later?)
  72.  */
  73. static int devpts_revalidate(struct dentry * dentry, int flags)
  74. {
  75. struct devpts_sb_info *sbi;
  76. if ( !dentry->d_inode )
  77. return 0;
  78. sbi = SBI(dentry->d_inode->i_sb);
  79. return ( sbi->inodes[dentry->d_inode->i_ino - 2] == dentry->d_inode );
  80. }
  81. static struct dentry *devpts_root_lookup(struct inode * dir, struct dentry * dentry)
  82. {
  83. struct devpts_sb_info *sbi = SBI(dir->i_sb);
  84. unsigned int entry;
  85. int i;
  86. const char *p;
  87. dentry->d_op    = &devpts_dentry_operations;
  88. if ( dentry->d_name.len == 1 && dentry->d_name.name[0] == '0' ) {
  89. entry = 0;
  90. } else if ( dentry->d_name.len < 1 ) {
  91. return NULL;
  92. } else {
  93. p = dentry->d_name.name;
  94. if ( *p < '1' || *p > '9' )
  95. return NULL;
  96. entry = *p++ - '0';
  97. for ( i = dentry->d_name.len-1 ; i ; i-- ) {
  98. unsigned int nentry = *p++ - '0';
  99. if ( nentry > 9 )
  100. return NULL;
  101. if ( entry >= ~0U/10 )
  102. return NULL;
  103. entry = nentry + entry * 10;
  104. }
  105. }
  106. if ( entry >= sbi->max_ptys )
  107. return NULL;
  108. if ( sbi->inodes[entry] )
  109. atomic_inc(&sbi->inodes[entry]->i_count);
  110. d_add(dentry, sbi->inodes[entry]);
  111. return NULL;
  112. }