stat.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/stat.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. #include <linux/config.h>
  7. #include <linux/mm.h>
  8. #include <linux/errno.h>
  9. #include <linux/file.h>
  10. #include <linux/smp_lock.h>
  11. #include <linux/highuid.h>
  12. #include <asm/uaccess.h>
  13. /*
  14.  * Revalidate the inode. This is required for proper NFS attribute caching.
  15.  */
  16. static __inline__ int
  17. do_revalidate(struct dentry *dentry)
  18. {
  19. struct inode * inode = dentry->d_inode;
  20. if (inode->i_op && inode->i_op->revalidate)
  21. return inode->i_op->revalidate(dentry);
  22. return 0;
  23. }
  24. #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && 
  25.     !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && 
  26.     !defined(__x86_64__)
  27. /*
  28.  * For backward compatibility?  Maybe this should be moved
  29.  * into arch/i386 instead?
  30.  */
  31. static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
  32. {
  33. static int warncount = 5;
  34. struct __old_kernel_stat tmp;
  35. if (warncount > 0) {
  36. warncount--;
  37. printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.n",
  38. current->comm);
  39. } else if (warncount < 0) {
  40. /* it's laughable, but... */
  41. warncount = 0;
  42. }
  43. tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  44. tmp.st_ino = inode->i_ino;
  45. tmp.st_mode = inode->i_mode;
  46. tmp.st_nlink = inode->i_nlink;
  47. SET_OLDSTAT_UID(tmp, inode->i_uid);
  48. SET_OLDSTAT_GID(tmp, inode->i_gid);
  49. tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  50. #if BITS_PER_LONG == 32
  51. if (inode->i_size > MAX_NON_LFS)
  52. return -EOVERFLOW;
  53. #endif
  54. tmp.st_size = inode->i_size;
  55. tmp.st_atime = inode->i_atime;
  56. tmp.st_mtime = inode->i_mtime;
  57. tmp.st_ctime = inode->i_ctime;
  58. return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  59. }
  60. #endif
  61. static int cp_new_stat(struct inode * inode, struct stat * statbuf)
  62. {
  63. struct stat tmp;
  64. unsigned int blocks, indirect;
  65. memset(&tmp, 0, sizeof(tmp));
  66. tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  67. tmp.st_ino = inode->i_ino;
  68. tmp.st_mode = inode->i_mode;
  69. tmp.st_nlink = inode->i_nlink;
  70. SET_STAT_UID(tmp, inode->i_uid);
  71. SET_STAT_GID(tmp, inode->i_gid);
  72. tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  73. #if BITS_PER_LONG == 32
  74. if (inode->i_size > MAX_NON_LFS)
  75. return -EOVERFLOW;
  76. #endif
  77. tmp.st_size = inode->i_size;
  78. tmp.st_atime = inode->i_atime;
  79. tmp.st_mtime = inode->i_mtime;
  80. tmp.st_ctime = inode->i_ctime;
  81. /*
  82.  * st_blocks and st_blksize are approximated with a simple algorithm if
  83.  * they aren't supported directly by the filesystem. The minix and msdos
  84.  * filesystems don't keep track of blocks, so they would either have to
  85.  * be counted explicitly (by delving into the file itself), or by using
  86.  * this simple algorithm to get a reasonable (although not 100% accurate)
  87.  * value.
  88.  */
  89. /*
  90.  * Use minix fs values for the number of direct and indirect blocks.  The
  91.  * count is now exact for the minix fs except that it counts zero blocks.
  92.  * Everything is in units of BLOCK_SIZE until the assignment to
  93.  * tmp.st_blksize.
  94.  */
  95. #define D_B   7
  96. #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  97. if (!inode->i_blksize) {
  98. blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
  99. if (blocks > D_B) {
  100. indirect = (blocks - D_B + I_B - 1) / I_B;
  101. blocks += indirect;
  102. if (indirect > 1) {
  103. indirect = (indirect - 1 + I_B - 1) / I_B;
  104. blocks += indirect;
  105. if (indirect > 1)
  106. blocks++;
  107. }
  108. }
  109. tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
  110. tmp.st_blksize = BLOCK_SIZE;
  111. } else {
  112. tmp.st_blocks = inode->i_blocks;
  113. tmp.st_blksize = inode->i_blksize;
  114. }
  115. return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  116. }
  117. #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && 
  118.     !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && 
  119.     !defined(__x86_64__)
  120. /*
  121.  * For backward compatibility?  Maybe this should be moved
  122.  * into arch/i386 instead?
  123.  */
  124. asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf)
  125. {
  126. struct nameidata nd;
  127. int error;
  128. error = user_path_walk(filename, &nd);
  129. if (!error) {
  130. error = do_revalidate(nd.dentry);
  131. if (!error)
  132. error = cp_old_stat(nd.dentry->d_inode, statbuf);
  133. path_release(&nd);
  134. }
  135. return error;
  136. }
  137. #endif
  138. asmlinkage long sys_newstat(char * filename, struct stat * statbuf)
  139. {
  140. struct nameidata nd;
  141. int error;
  142. error = user_path_walk(filename, &nd);
  143. if (!error) {
  144. error = do_revalidate(nd.dentry);
  145. if (!error)
  146. error = cp_new_stat(nd.dentry->d_inode, statbuf);
  147. path_release(&nd);
  148. }
  149. return error;
  150. }
  151. #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && 
  152.     !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && 
  153.     !defined(__x86_64__)
  154. /*
  155.  * For backward compatibility?  Maybe this should be moved
  156.  * into arch/i386 instead?
  157.  */
  158. asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf)
  159. {
  160. struct nameidata nd;
  161. int error;
  162. error = user_path_walk_link(filename, &nd);
  163. if (!error) {
  164. error = do_revalidate(nd.dentry);
  165. if (!error)
  166. error = cp_old_stat(nd.dentry->d_inode, statbuf);
  167. path_release(&nd);
  168. }
  169. return error;
  170. }
  171. #endif
  172. asmlinkage long sys_newlstat(char * filename, struct stat * statbuf)
  173. {
  174. struct nameidata nd;
  175. int error;
  176. error = user_path_walk_link(filename, &nd);
  177. if (!error) {
  178. error = do_revalidate(nd.dentry);
  179. if (!error)
  180. error = cp_new_stat(nd.dentry->d_inode, statbuf);
  181. path_release(&nd);
  182. }
  183. return error;
  184. }
  185. #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && 
  186.     !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__arm__) && 
  187.     !defined(__x86_64__)
  188. /*
  189.  * For backward compatibility?  Maybe this should be moved
  190.  * into arch/i386 instead?
  191.  */
  192. asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf)
  193. {
  194. struct file * f;
  195. int err = -EBADF;
  196. f = fget(fd);
  197. if (f) {
  198. struct dentry * dentry = f->f_dentry;
  199. err = do_revalidate(dentry);
  200. if (!err)
  201. err = cp_old_stat(dentry->d_inode, statbuf);
  202. fput(f);
  203. }
  204. return err;
  205. }
  206. #endif
  207. asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf)
  208. {
  209. struct file * f;
  210. int err = -EBADF;
  211. f = fget(fd);
  212. if (f) {
  213. struct dentry * dentry = f->f_dentry;
  214. err = do_revalidate(dentry);
  215. if (!err)
  216. err = cp_new_stat(dentry->d_inode, statbuf);
  217. fput(f);
  218. }
  219. return err;
  220. }
  221. asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
  222. {
  223. struct nameidata nd;
  224. int error;
  225. if (bufsiz <= 0)
  226. return -EINVAL;
  227. error = user_path_walk_link(path, &nd);
  228. if (!error) {
  229. struct inode * inode = nd.dentry->d_inode;
  230. error = -EINVAL;
  231. if (inode->i_op && inode->i_op->readlink &&
  232.     !(error = do_revalidate(nd.dentry))) {
  233. UPDATE_ATIME(inode);
  234. error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
  235. }
  236. path_release(&nd);
  237. }
  238. return error;
  239. }
  240. /* ---------- LFS-64 ----------- */
  241. #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X)
  242. static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
  243. {
  244. struct stat64 tmp;
  245. unsigned int blocks, indirect;
  246. memset(&tmp, 0, sizeof(tmp));
  247. tmp.st_dev = kdev_t_to_nr(inode->i_dev);
  248. tmp.st_ino = inode->i_ino;
  249. #ifdef STAT64_HAS_BROKEN_ST_INO
  250. tmp.__st_ino = inode->i_ino;
  251. #endif
  252. tmp.st_mode = inode->i_mode;
  253. tmp.st_nlink = inode->i_nlink;
  254. tmp.st_uid = inode->i_uid;
  255. tmp.st_gid = inode->i_gid;
  256. tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
  257. tmp.st_atime = inode->i_atime;
  258. tmp.st_mtime = inode->i_mtime;
  259. tmp.st_ctime = inode->i_ctime;
  260. tmp.st_size = inode->i_size;
  261. /*
  262.  * st_blocks and st_blksize are approximated with a simple algorithm if
  263.  * they aren't supported directly by the filesystem. The minix and msdos
  264.  * filesystems don't keep track of blocks, so they would either have to
  265.  * be counted explicitly (by delving into the file itself), or by using
  266.  * this simple algorithm to get a reasonable (although not 100% accurate)
  267.  * value.
  268.  */
  269. /*
  270.  * Use minix fs values for the number of direct and indirect blocks.  The
  271.  * count is now exact for the minix fs except that it counts zero blocks.
  272.  * Everything is in units of BLOCK_SIZE until the assignment to
  273.  * tmp.st_blksize.
  274.  */
  275. #define D_B   7
  276. #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
  277. if (!inode->i_blksize) {
  278. blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
  279. if (blocks > D_B) {
  280. indirect = (blocks - D_B + I_B - 1) / I_B;
  281. blocks += indirect;
  282. if (indirect > 1) {
  283. indirect = (indirect - 1 + I_B - 1) / I_B;
  284. blocks += indirect;
  285. if (indirect > 1)
  286. blocks++;
  287. }
  288. }
  289. tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
  290. tmp.st_blksize = BLOCK_SIZE;
  291. } else {
  292. tmp.st_blocks = inode->i_blocks;
  293. tmp.st_blksize = inode->i_blksize;
  294. }
  295. return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
  296. }
  297. asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags)
  298. {
  299. struct nameidata nd;
  300. int error;
  301. error = user_path_walk(filename, &nd);
  302. if (!error) {
  303. error = do_revalidate(nd.dentry);
  304. if (!error)
  305. error = cp_new_stat64(nd.dentry->d_inode, statbuf);
  306. path_release(&nd);
  307. }
  308. return error;
  309. }
  310. asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags)
  311. {
  312. struct nameidata nd;
  313. int error;
  314. error = user_path_walk_link(filename, &nd);
  315. if (!error) {
  316. error = do_revalidate(nd.dentry);
  317. if (!error)
  318. error = cp_new_stat64(nd.dentry->d_inode, statbuf);
  319. path_release(&nd);
  320. }
  321. return error;
  322. }
  323. asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags)
  324. {
  325. struct file * f;
  326. int err = -EBADF;
  327. f = fget(fd);
  328. if (f) {
  329. struct dentry * dentry = f->f_dentry;
  330. err = do_revalidate(dentry);
  331. if (!err)
  332. err = cp_new_stat64(dentry->d_inode, statbuf);
  333. fput(f);
  334. }
  335. return err;
  336. }
  337. #endif /* LFS-64 */