xattr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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. full_path = build_path_from_dentry(direntry);
  58. if(full_path == NULL) {
  59. FreeXid(xid);
  60. return -ENOMEM;
  61. }
  62. if(ea_name == NULL) {
  63. cFYI(1,("Null xattr names not supported"));
  64. } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
  65. && (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
  66. cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
  67. /* BB what if no namespace prefix? */
  68. /* Should we just pass them to server, except for
  69. system and perhaps security prefixes? */
  70. } else {
  71. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  72. goto remove_ea_exit;
  73. ea_name+=5; /* skip past user. prefix */
  74. rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
  75. (__u16)0, cifs_sb->local_nls,
  76. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  77. }
  78. remove_ea_exit:
  79. kfree(full_path);
  80. FreeXid(xid);
  81. #endif
  82. return rc;
  83. }
  84. int cifs_setxattr(struct dentry * direntry, const char * ea_name,
  85. const void * ea_value, size_t value_size, int flags)
  86. {
  87. int rc = -EOPNOTSUPP;
  88. #ifdef CONFIG_CIFS_XATTR
  89. int xid;
  90. struct cifs_sb_info *cifs_sb;
  91. struct cifsTconInfo *pTcon;
  92. struct super_block * sb;
  93. char * full_path;
  94. if(direntry == NULL)
  95. return -EIO;
  96. if(direntry->d_inode == NULL)
  97. return -EIO;
  98. sb = direntry->d_inode->i_sb;
  99. if(sb == NULL)
  100. return -EIO;
  101. xid = GetXid();
  102. cifs_sb = CIFS_SB(sb);
  103. pTcon = cifs_sb->tcon;
  104. full_path = build_path_from_dentry(direntry);
  105. if(full_path == NULL) {
  106. FreeXid(xid);
  107. return -ENOMEM;
  108. }
  109. /* return dos attributes as pseudo xattr */
  110. /* return alt name if available as pseudo attr */
  111. /* if proc/fs/cifs/streamstoxattr is set then
  112. search server for EAs or streams to
  113. returns as xattrs */
  114. if(value_size > MAX_EA_VALUE_SIZE) {
  115. cFYI(1,("size of EA value too large"));
  116. kfree(full_path);
  117. FreeXid(xid);
  118. return -EOPNOTSUPP;
  119. }
  120. if(ea_name == NULL) {
  121. cFYI(1,("Null xattr names not supported"));
  122. } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
  123. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  124. goto set_ea_exit;
  125. if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
  126. cFYI(1,("attempt to set cifs inode metadata"));
  127. }
  128. ea_name += 5; /* skip past user. prefix */
  129. rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
  130. (__u16)value_size, cifs_sb->local_nls,
  131. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  132. } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
  133. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  134. goto set_ea_exit;
  135. ea_name += 4; /* skip past os2. prefix */
  136. rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
  137. (__u16)value_size, cifs_sb->local_nls,
  138. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  139. } else {
  140. int temp;
  141. temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
  142. strlen(POSIX_ACL_XATTR_ACCESS));
  143. if (temp == 0) {
  144. #ifdef CONFIG_CIFS_POSIX
  145. if(sb->s_flags & MS_POSIXACL)
  146. rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
  147. ea_value, (const int)value_size,
  148. ACL_TYPE_ACCESS,cifs_sb->local_nls,
  149. cifs_sb->mnt_cifs_flags &
  150. CIFS_MOUNT_MAP_SPECIAL_CHR);
  151. cFYI(1,("set POSIX ACL rc %d",rc));
  152. #else
  153. cFYI(1,("set POSIX ACL not supported"));
  154. #endif
  155. } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
  156. #ifdef CONFIG_CIFS_POSIX
  157. if(sb->s_flags & MS_POSIXACL)
  158. rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
  159. ea_value, (const int)value_size,
  160. ACL_TYPE_DEFAULT, cifs_sb->local_nls,
  161. cifs_sb->mnt_cifs_flags &
  162. CIFS_MOUNT_MAP_SPECIAL_CHR);
  163. cFYI(1,("set POSIX default ACL rc %d",rc));
  164. #else
  165. cFYI(1,("set default POSIX ACL not supported"));
  166. #endif
  167. } else {
  168. cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
  169. /* BB what if no namespace prefix? */
  170. /* Should we just pass them to server, except for
  171. system and perhaps security prefixes? */
  172. }
  173. }
  174. set_ea_exit:
  175. kfree(full_path);
  176. FreeXid(xid);
  177. #endif
  178. return rc;
  179. }
  180. ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
  181. void * ea_value, size_t buf_size)
  182. {
  183. ssize_t rc = -EOPNOTSUPP;
  184. #ifdef CONFIG_CIFS_XATTR
  185. int xid;
  186. struct cifs_sb_info *cifs_sb;
  187. struct cifsTconInfo *pTcon;
  188. struct super_block * sb;
  189. char * full_path;
  190. if(direntry == NULL)
  191. return -EIO;
  192. if(direntry->d_inode == NULL)
  193. return -EIO;
  194. sb = direntry->d_inode->i_sb;
  195. if(sb == NULL)
  196. return -EIO;
  197. xid = GetXid();
  198. cifs_sb = CIFS_SB(sb);
  199. pTcon = cifs_sb->tcon;
  200. full_path = build_path_from_dentry(direntry);
  201. if(full_path == NULL) {
  202. FreeXid(xid);
  203. return -ENOMEM;
  204. }
  205. /* return dos attributes as pseudo xattr */
  206. /* return alt name if available as pseudo attr */
  207. if(ea_name == NULL) {
  208. cFYI(1,("Null xattr names not supported"));
  209. } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
  210. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  211. goto get_ea_exit;
  212. if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
  213. cFYI(1,("attempt to query cifs inode metadata"));
  214. /* revalidate/getattr then populate from inode */
  215. } /* BB add else when above is implemented */
  216. ea_name += 5; /* skip past user. prefix */
  217. rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
  218. buf_size, cifs_sb->local_nls,
  219. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  220. } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
  221. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  222. goto get_ea_exit;
  223. ea_name += 4; /* skip past os2. prefix */
  224. rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
  225. buf_size, cifs_sb->local_nls,
  226. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  227. } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
  228. strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
  229. #ifdef CONFIG_CIFS_POSIX
  230. if(sb->s_flags & MS_POSIXACL)
  231. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  232. ea_value, buf_size, ACL_TYPE_ACCESS,
  233. cifs_sb->local_nls,
  234. cifs_sb->mnt_cifs_flags &
  235. CIFS_MOUNT_MAP_SPECIAL_CHR);
  236. /* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
  237. __u16 fid;
  238. int oplock = FALSE;
  239. rc = CIFSSMBOpen(xid, pTcon, full_path,
  240. FILE_OPEN, GENERIC_READ, 0, &fid,
  241. &oplock, NULL, cifs_sb->local_nls,
  242. cifs_sb->mnt_cifs_flags &
  243. CIFS_MOUNT_MAP_SPECIAL_CHR);
  244. if(rc == 0) {
  245. rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
  246. ea_value, buf_size,
  247. ACL_TYPE_ACCESS);
  248. CIFSSMBClose(xid, pTcon, fid);
  249. }
  250. } */ /* BB enable after fixing up return data */
  251. #else
  252. cFYI(1,("query POSIX ACL not supported yet"));
  253. #endif /* CONFIG_CIFS_POSIX */
  254. } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
  255. strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
  256. #ifdef CONFIG_CIFS_POSIX
  257. if(sb->s_flags & MS_POSIXACL)
  258. rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
  259. ea_value, buf_size, ACL_TYPE_DEFAULT,
  260. cifs_sb->local_nls,
  261. cifs_sb->mnt_cifs_flags &
  262. CIFS_MOUNT_MAP_SPECIAL_CHR);
  263. #else
  264. cFYI(1,("query POSIX default ACL not supported yet"));
  265. #endif
  266. } else if(strncmp(ea_name,
  267. CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
  268. cFYI(1,("Trusted xattr namespace not supported yet"));
  269. } else if(strncmp(ea_name,
  270. CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
  271. cFYI(1,("Security xattr namespace not supported yet"));
  272. } else {
  273. cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
  274. }
  275. /* We could add an additional check for streams ie
  276. if proc/fs/cifs/streamstoxattr is set then
  277. search server for EAs or streams to
  278. returns as xattrs */
  279. if(rc == -EINVAL)
  280. rc = -EOPNOTSUPP;
  281. get_ea_exit:
  282. kfree(full_path);
  283. FreeXid(xid);
  284. #endif
  285. return rc;
  286. }
  287. ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
  288. {
  289. ssize_t rc = -EOPNOTSUPP;
  290. #ifdef CONFIG_CIFS_XATTR
  291. int xid;
  292. struct cifs_sb_info *cifs_sb;
  293. struct cifsTconInfo *pTcon;
  294. struct super_block * sb;
  295. char * full_path;
  296. if(direntry == NULL)
  297. return -EIO;
  298. if(direntry->d_inode == NULL)
  299. return -EIO;
  300. sb = direntry->d_inode->i_sb;
  301. if(sb == NULL)
  302. return -EIO;
  303. cifs_sb = CIFS_SB(sb);
  304. pTcon = cifs_sb->tcon;
  305. if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
  306. return -EOPNOTSUPP;
  307. xid = GetXid();
  308. full_path = build_path_from_dentry(direntry);
  309. if(full_path == NULL) {
  310. FreeXid(xid);
  311. return -ENOMEM;
  312. }
  313. /* return dos attributes as pseudo xattr */
  314. /* return alt name if available as pseudo attr */
  315. /* if proc/fs/cifs/streamstoxattr is set then
  316. search server for EAs or streams to
  317. returns as xattrs */
  318. rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
  319. cifs_sb->local_nls,
  320. cifs_sb->mnt_cifs_flags &
  321. CIFS_MOUNT_MAP_SPECIAL_CHR);
  322. kfree(full_path);
  323. FreeXid(xid);
  324. #endif
  325. return rc;
  326. }