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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.   File: fs/xattr.c
  3.   Extended attribute handling.
  4.   Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
  5.   Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
  6.  */
  7. #include <linux/fs.h>
  8. #include <linux/slab.h>
  9. #include <linux/vmalloc.h>
  10. #include <linux/smp_lock.h>
  11. #include <linux/file.h>
  12. #include <linux/xattr.h>
  13. #include <asm/uaccess.h>
  14. /*
  15.  * Extended attribute memory allocation wrappers, originally
  16.  * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
  17.  * The vmalloc use here is very uncommon - extended attributes
  18.  * are supposed to be small chunks of metadata, and it is quite
  19.  * unusual to have very many extended attributes, so lists tend
  20.  * to be quite short as well.  The 64K upper limit is derived
  21.  * from the extended attribute size limit used by XFS.
  22.  * Intentionally allow zero @size for value/list size requests.
  23.  */
  24. static void *
  25. xattr_alloc(size_t size, size_t limit)
  26. {
  27. void *ptr;
  28. if (size > limit)
  29. return ERR_PTR(-E2BIG);
  30. if (!size) /* size request, no buffer is needed */
  31. return NULL;
  32. else if (size <= PAGE_SIZE)
  33. ptr = kmalloc((unsigned long) size, GFP_KERNEL);
  34. else
  35. ptr = vmalloc((unsigned long) size);
  36. if (!ptr)
  37. return ERR_PTR(-ENOMEM);
  38. return ptr;
  39. }
  40. static void
  41. xattr_free(void *ptr, size_t size)
  42. {
  43. if (!size) /* size request, no buffer was needed */
  44. return;
  45. else if (size <= PAGE_SIZE)
  46. kfree(ptr);
  47. else
  48. vfree(ptr);
  49. }
  50. /*
  51.  * Extended attribute SET operations
  52.  */
  53. static long
  54. setxattr(struct dentry *d, char *name, void *value, size_t size, int flags)
  55. {
  56. int error;
  57. void *kvalue;
  58. char kname[XATTR_NAME_MAX + 1];
  59. if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
  60. return -EINVAL;
  61. error = strncpy_from_user(kname, name, sizeof(kname));
  62. if (error == 0 || error == sizeof(kname))
  63. error = -ERANGE;
  64. if (error < 0)
  65. return error;
  66. kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
  67. if (IS_ERR(kvalue))
  68. return PTR_ERR(kvalue);
  69. if (size > 0 && copy_from_user(kvalue, value, size)) {
  70. xattr_free(kvalue, size);
  71. return -EFAULT;
  72. }
  73. error = -EOPNOTSUPP;
  74. if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
  75. down(&d->d_inode->i_sem);
  76. lock_kernel();
  77. error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
  78. unlock_kernel();
  79. up(&d->d_inode->i_sem);
  80. }
  81. xattr_free(kvalue, size);
  82. return error;
  83. }
  84. asmlinkage long
  85. sys_setxattr(char *path, char *name, void *value, size_t size, int flags)
  86. {
  87. struct nameidata nd;
  88. int error;
  89. error = user_path_walk(path, &nd);
  90. if (error)
  91. return error;
  92. error = setxattr(nd.dentry, name, value, size, flags);
  93. path_release(&nd);
  94. return error;
  95. }
  96. asmlinkage long
  97. sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags)
  98. {
  99. struct nameidata nd;
  100. int error;
  101. error = user_path_walk_link(path, &nd);
  102. if (error)
  103. return error;
  104. error = setxattr(nd.dentry, name, value, size, flags);
  105. path_release(&nd);
  106. return error;
  107. }
  108. asmlinkage long
  109. sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags)
  110. {
  111. struct file *f;
  112. int error = -EBADF;
  113. f = fget(fd);
  114. if (!f)
  115. return error;
  116. error = setxattr(f->f_dentry, name, value, size, flags);
  117. fput(f);
  118. return error;
  119. }
  120. /*
  121.  * Extended attribute GET operations
  122.  */
  123. static ssize_t
  124. getxattr(struct dentry *d, char *name, void *value, size_t size)
  125. {
  126. ssize_t error;
  127. void *kvalue;
  128. char kname[XATTR_NAME_MAX + 1];
  129. error = strncpy_from_user(kname, name, sizeof(kname));
  130. if (error == 0 || error == sizeof(kname))
  131. error = -ERANGE;
  132. if (error < 0)
  133. return error;
  134. kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
  135. if (IS_ERR(kvalue))
  136. return PTR_ERR(kvalue);
  137. error = -EOPNOTSUPP;
  138. if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
  139. down(&d->d_inode->i_sem);
  140. lock_kernel();
  141. error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
  142. unlock_kernel();
  143. up(&d->d_inode->i_sem);
  144. }
  145. if (kvalue && error > 0)
  146. if (copy_to_user(value, kvalue, error))
  147. error = -EFAULT;
  148. xattr_free(kvalue, size);
  149. return error;
  150. }
  151. asmlinkage ssize_t
  152. sys_getxattr(char *path, char *name, void *value, size_t size)
  153. {
  154. struct nameidata nd;
  155. ssize_t error;
  156. error = user_path_walk(path, &nd);
  157. if (error)
  158. return error;
  159. error = getxattr(nd.dentry, name, value, size);
  160. path_release(&nd);
  161. return error;
  162. }
  163. asmlinkage ssize_t
  164. sys_lgetxattr(char *path, char *name, void *value, size_t size)
  165. {
  166. struct nameidata nd;
  167. ssize_t error;
  168. error = user_path_walk_link(path, &nd);
  169. if (error)
  170. return error;
  171. error = getxattr(nd.dentry, name, value, size);
  172. path_release(&nd);
  173. return error;
  174. }
  175. asmlinkage ssize_t
  176. sys_fgetxattr(int fd, char *name, void *value, size_t size)
  177. {
  178. struct file *f;
  179. ssize_t error = -EBADF;
  180. f = fget(fd);
  181. if (!f)
  182. return error;
  183. error = getxattr(f->f_dentry, name, value, size);
  184. fput(f);
  185. return error;
  186. }
  187. /*
  188.  * Extended attribute LIST operations
  189.  */
  190. static ssize_t
  191. listxattr(struct dentry *d, char *list, size_t size)
  192. {
  193. ssize_t error;
  194. char *klist;
  195. klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
  196. if (IS_ERR(klist))
  197. return PTR_ERR(klist);
  198. error = -EOPNOTSUPP;
  199. if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
  200. down(&d->d_inode->i_sem);
  201. lock_kernel();
  202. error = d->d_inode->i_op->listxattr(d, klist, size);
  203. unlock_kernel();
  204. up(&d->d_inode->i_sem);
  205. }
  206. if (klist && error > 0)
  207. if (copy_to_user(list, klist, error))
  208. error = -EFAULT;
  209. xattr_free(klist, size);
  210. return error;
  211. }
  212. asmlinkage ssize_t
  213. sys_listxattr(char *path, char *list, size_t size)
  214. {
  215. struct nameidata nd;
  216. ssize_t error;
  217. error = user_path_walk(path, &nd);
  218. if (error)
  219. return error;
  220. error = listxattr(nd.dentry, list, size);
  221. path_release(&nd);
  222. return error;
  223. }
  224. asmlinkage ssize_t
  225. sys_llistxattr(char *path, char *list, size_t size)
  226. {
  227. struct nameidata nd;
  228. ssize_t error;
  229. error = user_path_walk_link(path, &nd);
  230. if (error)
  231. return error;
  232. error = listxattr(nd.dentry, list, size);
  233. path_release(&nd);
  234. return error;
  235. }
  236. asmlinkage ssize_t
  237. sys_flistxattr(int fd, char *list, size_t size)
  238. {
  239. struct file *f;
  240. ssize_t error = -EBADF;
  241. f = fget(fd);
  242. if (!f)
  243. return error;
  244. error = listxattr(f->f_dentry, list, size);
  245. fput(f);
  246. return error;
  247. }
  248. /*
  249.  * Extended attribute REMOVE operations
  250.  */
  251. static long
  252. removexattr(struct dentry *d, char *name)
  253. {
  254. int error;
  255. char kname[XATTR_NAME_MAX + 1];
  256. error = strncpy_from_user(kname, name, sizeof(kname));
  257. if (error == 0 || error == sizeof(kname))
  258. error = -ERANGE;
  259. if (error < 0)
  260. return error;
  261. error = -EOPNOTSUPP;
  262. if (d->d_inode->i_op && d->d_inode->i_op->removexattr) {
  263. down(&d->d_inode->i_sem);
  264. lock_kernel();
  265. error = d->d_inode->i_op->removexattr(d, kname);
  266. unlock_kernel();
  267. up(&d->d_inode->i_sem);
  268. }
  269. return error;
  270. }
  271. asmlinkage long
  272. sys_removexattr(char *path, char *name)
  273. {
  274. struct nameidata nd;
  275. int error;
  276. error = user_path_walk(path, &nd);
  277. if (error)
  278. return error;
  279. error = removexattr(nd.dentry, name);
  280. path_release(&nd);
  281. return error;
  282. }
  283. asmlinkage long
  284. sys_lremovexattr(char *path, char *name)
  285. {
  286. struct nameidata nd;
  287. int error;
  288. error = user_path_walk_link(path, &nd);
  289. if (error)
  290. return error;
  291. error = removexattr(nd.dentry, name);
  292. path_release(&nd);
  293. return error;
  294. }
  295. asmlinkage long
  296. sys_fremovexattr(int fd, char *name)
  297. {
  298. struct file *f;
  299. int error = -EBADF;
  300. f = fget(fd);
  301. if (!f)
  302. return error;
  303. error = removexattr(f->f_dentry, name);
  304. fput(f);
  305. return error;
  306. }