xattr.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * fs/cifs/xattr.c
  3. *
  4. * Copyright (c) International Business Machines Corp., 2003
  5. * Author(s): Steve French (sfrench@us.ibm.com)
  6. *
  7. * This library is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published
  9. * by the Free Software Foundation; either version 2.1 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  15. * the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <linux/fs.h>
  22. #include <linux/posix_acl_xattr.h>
  23. #include "cifsfs.h"
  24. #include "cifspdu.h"
  25. #include "cifsglob.h"
  26. #include "cifsproto.h"
  27. #include "cifs_debug.h"
  28. #define MAX_EA_VALUE_SIZE 65535
  29. #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
  30. #define CIFS_XATTR_USER_PREFIX "user."
  31. #define CIFS_XATTR_SYSTEM_PREFIX "system."
  32. #define CIFS_XATTR_OS2_PREFIX "os2."
  33. #define CIFS_XATTR_SECURITY_PREFIX ".security"
  34. #define CIFS_XATTR_TRUSTED_PREFIX "trusted."
  35. #define XATTR_TRUSTED_PREFIX_LEN 8
  36. #define XATTR_SECURITY_PREFIX_LEN 9
  37. /* BB need to add server (Samba e.g) support for security and trusted prefix */
  38. int cifs_removexattr(struct dentry * direntry, const char * ea_name)
  39. {
  40. int rc = -EOPNOTSUPP;
  41. #ifdef CONFIG_CIFS_XATTR
  42. int xid;
  43. struct cifs_sb_info *cifs_sb;
  44. struct cifsTconInfo *pTcon;
  45. struct super_block * sb;
  46. char * full_path;
  47. if(direntry == NULL)
  48. return -EIO;
  49. if(direntry->d_inode == NULL)
  50. return -EIO;
  51. sb = direntry->d_inode->i_sb;
  52. if(sb == NULL)
  53. return -EIO;
  54. xid = GetXid();
  55. cifs_sb = CIFS_SB(sb);
  56. pTcon = cifs_sb->tcon;
  57. down(&sb->s_vfs_rename_sem);
  58. full_path = build_path_from_dentry(direntry);
  59. up(&sb->s_vfs_rename_sem);
  60. if(full_path == NULL) {
  61. FreeXid(xid);
  62. return -ENOMEM;
  63. }
  64. if(ea_name == NULL) {
  65. cFYI(1,("Null xattr names not supported"));
  66. } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
  67. && (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
  68. cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
  69. /* BB what if no namespace prefix? */
  70. /* Should we just pass them to server, except for
  71. system and perhaps security prefixes? */
  72. } else {
  73. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  74. goto remove_ea_exit;
  75. ea_name+=5; /* skip past user. prefix */
  76. rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
  77. (__u16)0, cifs_sb->local_nls,
  78. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  79. }
  80. remove_ea_exit:
  81. if (full_path)
  82. kfree(full_path);
  83. FreeXid(xid);
  84. #endif
  85. return rc;
  86. }
  87. int cifs_setxattr(struct dentry * direntry, const char * ea_name,
  88. const void * ea_value, size_t value_size, int flags)
  89. {
  90. int rc = -EOPNOTSUPP;
  91. #ifdef CONFIG_CIFS_XATTR
  92. int xid;
  93. struct cifs_sb_info *cifs_sb;
  94. struct cifsTconInfo *pTcon;
  95. struct super_block * sb;
  96. char * full_path;
  97. if(direntry == NULL)
  98. return -EIO;
  99. if(direntry->d_inode == NULL)
  100. return -EIO;
  101. sb = direntry->d_inode->i_sb;
  102. if(sb == NULL)
  103. return -EIO;
  104. xid = GetXid();
  105. cifs_sb = CIFS_SB(sb);
  106. pTcon = cifs_sb->tcon;
  107. down(&sb->s_vfs_rename_sem);
  108. full_path = build_path_from_dentry(direntry);
  109. up(&sb->s_vfs_rename_sem);
  110. if(full_path == NULL) {
  111. FreeXid(xid);
  112. return -ENOMEM;
  113. }
  114. /* return dos attributes as pseudo xattr */
  115. /* return alt name if available as pseudo attr */
  116. /* if proc/fs/cifs/streamstoxattr is set then
  117. search server for EAs or streams to
  118. returns as xattrs */
  119. if(value_size > MAX_EA_VALUE_SIZE) {
  120. cFYI(1,("size of EA value too large"));
  121. if(full_path)
  122. kfree(full_path);
  123. FreeXid(xid);
  124. return -EOPNOTSUPP;
  125. }
  126. if(ea_name == NULL) {
  127. cFYI(1,("Null xattr names not supported"));
  128. } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
  129. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  130. goto set_ea_exit;
  131. if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
  132. cFYI(1,("attempt to set cifs inode metadata"));
  133. }
  134. ea_name += 5; /* skip past user. prefix */
  135. rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
  136. (__u16)value_size, cifs_sb->local_nls,
  137. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  138. } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
  139. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  140. goto set_ea_exit;
  141. ea_name += 4; /* skip past os2. prefix */
  142. rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
  143. (__u16)value_size, cifs_sb->local_nls,
  144. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  145. } else {
  146. int temp;
  147. temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
  148. strlen(POSIX_ACL_XATTR_ACCESS));
  149. if (temp == 0) {
  150. #ifdef CONFIG_CIFS_POSIX
  151. if(sb->s_flags & MS_POSIXACL)
  152. rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
  153. ea_value, (const int)value_size,
  154. ACL_TYPE_ACCESS,cifs_sb->local_nls,
  155. cifs_sb->mnt_cifs_flags &
  156. CIFS_MOUNT_MAP_SPECIAL_CHR);
  157. cFYI(1,("set POSIX ACL rc %d",rc));
  158. #else
  159. cFYI(1,("set POSIX ACL not supported"));
  160. #endif
  161. } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
  162. #ifdef CONFIG_CIFS_POSIX
  163. if(sb->s_flags & MS_POSIXACL)
  164. rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
  165. ea_value, (const int)value_size,
  166. ACL_TYPE_DEFAULT, cifs_sb->local_nls,
  167. cifs_sb->mnt_cifs_flags &
  168. CIFS_MOUNT_MAP_SPECIAL_CHR);
  169. cFYI(1,("set POSIX default ACL rc %d",rc));
  170. #else
  171. cFYI(1,("set default POSIX ACL not supported"));
  172. #endif
  173. } else {
  174. cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
  175. /* BB what if no namespace prefix? */
  176. /* Should we just pass them to server, except for
  177. system and perhaps security prefixes? */
  178. }
  179. }
  180. set_ea_exit:
  181. if (full_path)
  182. kfree(full_path);
  183. FreeXid(xid);
  184. #endif
  185. return rc;
  186. }
  187. ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
  188. void * ea_value, size_t buf_size)
  189. {
  190. ssize_t rc = -EOPNOTSUPP;
  191. #ifdef CONFIG_CIFS_XATTR
  192. int xid;
  193. struct cifs_sb_info *cifs_sb;
  194. struct cifsTconInfo *pTcon;
  195. struct super_block * sb;
  196. char * full_path;
  197. if(direntry == NULL)
  198. return -EIO;
  199. if(direntry->d_inode == NULL)
  200. return -EIO;
  201. sb = direntry->d_inode->i_sb;
  202. if(sb == NULL)
  203. return -EIO;
  204. xid = GetXid();
  205. cifs_sb = CIFS_SB(sb);
  206. pTcon = cifs_sb->tcon;
  207. down(&sb->s_vfs_rename_sem);
  208. full_path = build_path_from_dentry(direntry);
  209. up(&sb->s_vfs_rename_sem);
  210. if(full_path == NULL) {
  211. FreeXid(xid);
  212. return -ENOMEM;
  213. }
  214. /* return dos attributes as pseudo xattr */
  215. /* return alt name if available as pseudo attr */
  216. if(ea_name == NULL) {
  217. cFYI(1,("Null xattr names not supported"));
  218. } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
  219. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  220. goto get_ea_exit;
  221. if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
  222. cFYI(1,("attempt to query cifs inode metadata"));
  223. /* revalidate/getattr then populate from inode */
  224. } /* BB add else when above is implemented */
  225. ea_name += 5; /* skip past user. prefix */
  226. rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
  227. buf_size, cifs_sb->local_nls,
  228. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  229. } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
  230. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  231. goto get_ea_exit;
  232. ea_name += 4; /* skip past os2. prefix */
  233. rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
  234. buf_size, cifs_sb->local_nls,
  235. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  236. } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
  237. #ifdef CONFIG_CIFS_POSIX
  238. if(sb->s_flags & MS_POSIXACL)
  239. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  240. ea_value, buf_size, ACL_TYPE_ACCESS,
  241. cifs_sb->local_nls,
  242. cifs_sb->mnt_cifs_flags &
  243. CIFS_MOUNT_MAP_SPECIAL_CHR);
  244. #else
  245. cFYI(1,("query POSIX ACL not supported yet"));
  246. #endif /* CONFIG_CIFS_POSIX */
  247. } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
  248. #ifdef CONFIG_CIFS_POSIX
  249. if(sb->s_flags & MS_POSIXACL)
  250. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  251. ea_value, buf_size, ACL_TYPE_DEFAULT,
  252. cifs_sb->local_nls,
  253. cifs_sb->mnt_cifs_flags &
  254. CIFS_MOUNT_MAP_SPECIAL_CHR);
  255. #else
  256. cFYI(1,("query POSIX default ACL not supported yet"));
  257. #endif
  258. } else if(strncmp(ea_name,
  259. CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
  260. cFYI(1,("Trusted xattr namespace not supported yet"));
  261. } else if(strncmp(ea_name,
  262. CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
  263. cFYI(1,("Security xattr namespace not supported yet"));
  264. } else {
  265. cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
  266. }
  267. /* We could add an additional check for streams ie
  268. if proc/fs/cifs/streamstoxattr is set then
  269. search server for EAs or streams to
  270. returns as xattrs */
  271. if(rc == -EINVAL)
  272. rc = -EOPNOTSUPP;
  273. get_ea_exit:
  274. if (full_path)
  275. kfree(full_path);
  276. FreeXid(xid);
  277. #endif
  278. return rc;
  279. }
  280. ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
  281. {
  282. ssize_t rc = -EOPNOTSUPP;
  283. #ifdef CONFIG_CIFS_XATTR
  284. int xid;
  285. struct cifs_sb_info *cifs_sb;
  286. struct cifsTconInfo *pTcon;
  287. struct super_block * sb;
  288. char * full_path;
  289. if(direntry == NULL)
  290. return -EIO;
  291. if(direntry->d_inode == NULL)
  292. return -EIO;
  293. sb = direntry->d_inode->i_sb;
  294. if(sb == NULL)
  295. return -EIO;
  296. xid = GetXid();
  297. cifs_sb = CIFS_SB(sb);
  298. pTcon = cifs_sb->tcon;
  299. down(&sb->s_vfs_rename_sem);
  300. full_path = build_path_from_dentry(direntry);
  301. up(&sb->s_vfs_rename_sem);
  302. if(full_path == NULL) {
  303. FreeXid(xid);
  304. return -ENOMEM;
  305. }
  306. /* return dos attributes as pseudo xattr */
  307. /* return alt name if available as pseudo attr */
  308. /* if proc/fs/cifs/streamstoxattr is set then
  309. search server for EAs or streams to
  310. returns as xattrs */
  311. rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
  312. cifs_sb->local_nls,
  313. cifs_sb->mnt_cifs_flags &
  314. CIFS_MOUNT_MAP_SPECIAL_CHR);
  315. if (full_path)
  316. kfree(full_path);
  317. FreeXid(xid);
  318. #endif
  319. return rc;
  320. }