statfs.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include <linux/syscalls.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/file.h>
  5. #include <linux/namei.h>
  6. #include <linux/statfs.h>
  7. #include <linux/security.h>
  8. #include <linux/uaccess.h>
  9. int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  10. {
  11. int retval = -ENODEV;
  12. if (dentry) {
  13. retval = -ENOSYS;
  14. if (dentry->d_sb->s_op->statfs) {
  15. memset(buf, 0, sizeof(*buf));
  16. retval = security_sb_statfs(dentry);
  17. if (retval)
  18. return retval;
  19. retval = dentry->d_sb->s_op->statfs(dentry, buf);
  20. if (retval == 0 && buf->f_frsize == 0)
  21. buf->f_frsize = buf->f_bsize;
  22. }
  23. }
  24. return retval;
  25. }
  26. EXPORT_SYMBOL(vfs_statfs);
  27. static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
  28. {
  29. struct kstatfs st;
  30. int retval;
  31. retval = vfs_statfs(dentry, &st);
  32. if (retval)
  33. return retval;
  34. if (sizeof(*buf) == sizeof(st))
  35. memcpy(buf, &st, sizeof(st));
  36. else {
  37. if (sizeof buf->f_blocks == 4) {
  38. if ((st.f_blocks | st.f_bfree | st.f_bavail |
  39. st.f_bsize | st.f_frsize) &
  40. 0xffffffff00000000ULL)
  41. return -EOVERFLOW;
  42. /*
  43. * f_files and f_ffree may be -1; it's okay to stuff
  44. * that into 32 bits
  45. */
  46. if (st.f_files != -1 &&
  47. (st.f_files & 0xffffffff00000000ULL))
  48. return -EOVERFLOW;
  49. if (st.f_ffree != -1 &&
  50. (st.f_ffree & 0xffffffff00000000ULL))
  51. return -EOVERFLOW;
  52. }
  53. buf->f_type = st.f_type;
  54. buf->f_bsize = st.f_bsize;
  55. buf->f_blocks = st.f_blocks;
  56. buf->f_bfree = st.f_bfree;
  57. buf->f_bavail = st.f_bavail;
  58. buf->f_files = st.f_files;
  59. buf->f_ffree = st.f_ffree;
  60. buf->f_fsid = st.f_fsid;
  61. buf->f_namelen = st.f_namelen;
  62. buf->f_frsize = st.f_frsize;
  63. memset(buf->f_spare, 0, sizeof(buf->f_spare));
  64. }
  65. return 0;
  66. }
  67. static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
  68. {
  69. struct kstatfs st;
  70. int retval;
  71. retval = vfs_statfs(dentry, &st);
  72. if (retval)
  73. return retval;
  74. if (sizeof(*buf) == sizeof(st))
  75. memcpy(buf, &st, sizeof(st));
  76. else {
  77. buf->f_type = st.f_type;
  78. buf->f_bsize = st.f_bsize;
  79. buf->f_blocks = st.f_blocks;
  80. buf->f_bfree = st.f_bfree;
  81. buf->f_bavail = st.f_bavail;
  82. buf->f_files = st.f_files;
  83. buf->f_ffree = st.f_ffree;
  84. buf->f_fsid = st.f_fsid;
  85. buf->f_namelen = st.f_namelen;
  86. buf->f_frsize = st.f_frsize;
  87. memset(buf->f_spare, 0, sizeof(buf->f_spare));
  88. }
  89. return 0;
  90. }
  91. SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
  92. {
  93. struct path path;
  94. int error;
  95. error = user_path(pathname, &path);
  96. if (!error) {
  97. struct statfs tmp;
  98. error = vfs_statfs_native(path.dentry, &tmp);
  99. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  100. error = -EFAULT;
  101. path_put(&path);
  102. }
  103. return error;
  104. }
  105. SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
  106. {
  107. struct path path;
  108. long error;
  109. if (sz != sizeof(*buf))
  110. return -EINVAL;
  111. error = user_path(pathname, &path);
  112. if (!error) {
  113. struct statfs64 tmp;
  114. error = vfs_statfs64(path.dentry, &tmp);
  115. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  116. error = -EFAULT;
  117. path_put(&path);
  118. }
  119. return error;
  120. }
  121. SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
  122. {
  123. struct file *file;
  124. struct statfs tmp;
  125. int error;
  126. error = -EBADF;
  127. file = fget(fd);
  128. if (!file)
  129. goto out;
  130. error = vfs_statfs_native(file->f_path.dentry, &tmp);
  131. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  132. error = -EFAULT;
  133. fput(file);
  134. out:
  135. return error;
  136. }
  137. SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
  138. {
  139. struct file *file;
  140. struct statfs64 tmp;
  141. int error;
  142. if (sz != sizeof(*buf))
  143. return -EINVAL;
  144. error = -EBADF;
  145. file = fget(fd);
  146. if (!file)
  147. goto out;
  148. error = vfs_statfs64(file->f_path.dentry, &tmp);
  149. if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  150. error = -EFAULT;
  151. fput(file);
  152. out:
  153. return error;
  154. }
  155. SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
  156. {
  157. struct super_block *s;
  158. struct ustat tmp;
  159. struct kstatfs sbuf;
  160. int err;
  161. s = user_get_super(new_decode_dev(dev));
  162. if (!s)
  163. return -EINVAL;
  164. err = vfs_statfs(s->s_root, &sbuf);
  165. drop_super(s);
  166. if (err)
  167. return err;
  168. memset(&tmp,0,sizeof(struct ustat));
  169. tmp.f_tfree = sbuf.f_bfree;
  170. tmp.f_tinode = sbuf.f_ffree;
  171. return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
  172. }