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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/ioctl.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. #include <linux/mm.h>
  7. #include <linux/smp_lock.h>
  8. #include <linux/file.h>
  9. #include <asm/uaccess.h>
  10. #include <asm/ioctls.h>
  11. static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
  12. {
  13. int error;
  14. int block;
  15. struct inode * inode = filp->f_dentry->d_inode;
  16. switch (cmd) {
  17. case FIBMAP:
  18. {
  19. struct address_space *mapping = inode->i_mapping;
  20. int res;
  21. /* do we support this mess? */
  22. if (!mapping->a_ops->bmap)
  23. return -EINVAL;
  24. if (!capable(CAP_SYS_RAWIO))
  25. return -EPERM;
  26. if ((error = get_user(block, (int *) arg)) != 0)
  27. return error;
  28. res = mapping->a_ops->bmap(mapping, block);
  29. return put_user(res, (int *) arg);
  30. }
  31. case FIGETBSZ:
  32. if (inode->i_sb == NULL)
  33. return -EBADF;
  34. return put_user(inode->i_sb->s_blocksize, (int *) arg);
  35. case FIONREAD:
  36. return put_user(inode->i_size - filp->f_pos, (int *) arg);
  37. }
  38. if (filp->f_op && filp->f_op->ioctl)
  39. return filp->f_op->ioctl(inode, filp, cmd, arg);
  40. return -ENOTTY;
  41. }
  42. asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  43. {
  44. struct file * filp;
  45. unsigned int flag;
  46. int on, error = -EBADF;
  47. filp = fget(fd);
  48. if (!filp)
  49. goto out;
  50. error = 0;
  51. lock_kernel();
  52. switch (cmd) {
  53. case FIOCLEX:
  54. set_close_on_exec(fd, 1);
  55. break;
  56. case FIONCLEX:
  57. set_close_on_exec(fd, 0);
  58. break;
  59. case FIONBIO:
  60. if ((error = get_user(on, (int *)arg)) != 0)
  61. break;
  62. flag = O_NONBLOCK;
  63. #ifdef __sparc__
  64. /* SunOS compatibility item. */
  65. if(O_NONBLOCK != O_NDELAY)
  66. flag |= O_NDELAY;
  67. #endif
  68. if (on)
  69. filp->f_flags |= flag;
  70. else
  71. filp->f_flags &= ~flag;
  72. break;
  73. case FIOASYNC:
  74. if ((error = get_user(on, (int *)arg)) != 0)
  75. break;
  76. flag = on ? FASYNC : 0;
  77. /* Did FASYNC state change ? */
  78. if ((flag ^ filp->f_flags) & FASYNC) {
  79. if (filp->f_op && filp->f_op->fasync)
  80. error = filp->f_op->fasync(fd, filp, on);
  81. else error = -ENOTTY;
  82. }
  83. if (error != 0)
  84. break;
  85. if (on)
  86. filp->f_flags |= FASYNC;
  87. else
  88. filp->f_flags &= ~FASYNC;
  89. break;
  90. default:
  91. error = -ENOTTY;
  92. if (S_ISREG(filp->f_dentry->d_inode->i_mode))
  93. error = file_ioctl(filp, cmd, arg);
  94. else if (filp->f_op && filp->f_op->ioctl)
  95. error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
  96. }
  97. unlock_kernel();
  98. fput(filp);
  99. out:
  100. return error;
  101. }