blob: a264b744bb41f4e62d9375b496758d5450520460 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/cifs/xattr.c
3 *
Steve French79a58d12007-07-06 22:44:50 +00004 * Copyright (c) International Business Machines Corp., 2003, 2007
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * 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
22#include <linux/fs.h>
23#include <linux/posix_acl_xattr.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include "cifsfs.h"
26#include "cifspdu.h"
27#include "cifsglob.h"
28#include "cifsproto.h"
29#include "cifs_debug.h"
30
31#define MAX_EA_VALUE_SIZE 65535
32#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
33#define CIFS_XATTR_USER_PREFIX "user."
34#define CIFS_XATTR_SYSTEM_PREFIX "system."
35#define CIFS_XATTR_OS2_PREFIX "os2."
36#define CIFS_XATTR_SECURITY_PREFIX ".security"
37#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
38#define XATTR_TRUSTED_PREFIX_LEN 8
39#define XATTR_SECURITY_PREFIX_LEN 9
40/* BB need to add server (Samba e.g) support for security and trusted prefix */
Steve French50c2f752007-07-13 00:33:32 +000041
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43
Steve French79a58d12007-07-06 22:44:50 +000044int cifs_removexattr(struct dentry *direntry, const char *ea_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045{
46 int rc = -EOPNOTSUPP;
47#ifdef CONFIG_CIFS_XATTR
48 int xid;
49 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -040050 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 struct cifsTconInfo *pTcon;
Steve French79a58d12007-07-06 22:44:50 +000052 struct super_block *sb;
Jeff Layton7ffec372010-09-29 19:51:11 -040053 char *full_path = NULL;
Steve French79a58d12007-07-06 22:44:50 +000054
55 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 return -EIO;
Steve French79a58d12007-07-06 22:44:50 +000057 if (direntry->d_inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 return -EIO;
59 sb = direntry->d_inode->i_sb;
Steve French79a58d12007-07-06 22:44:50 +000060 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 return -EIO;
Steve French79a58d12007-07-06 22:44:50 +000062
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -040064 tlink = cifs_sb_tlink(cifs_sb);
65 if (IS_ERR(tlink))
66 return PTR_ERR(tlink);
67 pTcon = tlink_tcon(tlink);
68
69 xid = GetXid();
Steve French79a58d12007-07-06 22:44:50 +000070
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +000072 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +053073 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -040074 goto remove_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -070075 }
Steve French79a58d12007-07-06 22:44:50 +000076 if (ea_name == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +000077 cFYI(1, "Null xattr names not supported");
Steve French79a58d12007-07-06 22:44:50 +000078 } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5)
79 && (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) {
80 cFYI(1,
Joe Perchesb6b38f72010-04-21 03:50:45 +000081 "illegal xattr request %s (only user namespace supported)",
82 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 /* BB what if no namespace prefix? */
84 /* Should we just pass them to server, except for
85 system and perhaps security prefixes? */
86 } else {
Steve French79a58d12007-07-06 22:44:50 +000087 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 goto remove_ea_exit;
89
Steve French79a58d12007-07-06 22:44:50 +000090 ea_name += 5; /* skip past user. prefix */
91 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
Steve French737b7582005-04-28 22:41:06 -070092 (__u16)0, cifs_sb->local_nls,
93 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094 }
95remove_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -080096 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -040098 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099#endif
100 return rc;
101}
102
Steve French79a58d12007-07-06 22:44:50 +0000103int cifs_setxattr(struct dentry *direntry, const char *ea_name,
104 const void *ea_value, size_t value_size, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105{
106 int rc = -EOPNOTSUPP;
107#ifdef CONFIG_CIFS_XATTR
108 int xid;
109 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -0400110 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 struct cifsTconInfo *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000112 struct super_block *sb;
113 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Steve French79a58d12007-07-06 22:44:50 +0000115 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 return -EIO;
Steve French79a58d12007-07-06 22:44:50 +0000117 if (direntry->d_inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 return -EIO;
119 sb = direntry->d_inode->i_sb;
Steve French79a58d12007-07-06 22:44:50 +0000120 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
123 cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400124 tlink = cifs_sb_tlink(cifs_sb);
125 if (IS_ERR(tlink))
126 return PTR_ERR(tlink);
127 pTcon = tlink_tcon(tlink);
128
129 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000132 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530133 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400134 goto set_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 }
136 /* return dos attributes as pseudo xattr */
137 /* return alt name if available as pseudo attr */
138
139 /* if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000140 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 returns as xattrs */
Steve French79a58d12007-07-06 22:44:50 +0000142 if (value_size > MAX_EA_VALUE_SIZE) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000143 cFYI(1, "size of EA value too large");
Jeff Layton7ffec372010-09-29 19:51:11 -0400144 rc = -EOPNOTSUPP;
145 goto set_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 }
147
Steve French79a58d12007-07-06 22:44:50 +0000148 if (ea_name == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000149 cFYI(1, "Null xattr names not supported");
Steve French79a58d12007-07-06 22:44:50 +0000150 } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
151 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 goto set_ea_exit;
Steve Frenchad7a2922008-02-07 23:25:02 +0000153 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)
Joe Perchesb6b38f72010-04-21 03:50:45 +0000154 cFYI(1, "attempt to set cifs inode metadata");
Steve Frenchad7a2922008-02-07 23:25:02 +0000155
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 ea_name += 5; /* skip past user. prefix */
Steve French79a58d12007-07-06 22:44:50 +0000157 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
Steve French737b7582005-04-28 22:41:06 -0700158 (__u16)value_size, cifs_sb->local_nls,
159 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French79a58d12007-07-06 22:44:50 +0000160 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
161 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 goto set_ea_exit;
163
164 ea_name += 4; /* skip past os2. prefix */
Steve French79a58d12007-07-06 22:44:50 +0000165 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
Steve French737b7582005-04-28 22:41:06 -0700166 (__u16)value_size, cifs_sb->local_nls,
167 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 } else {
Steve French79a58d12007-07-06 22:44:50 +0000169 int temp;
170 temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 strlen(POSIX_ACL_XATTR_ACCESS));
172 if (temp == 0) {
173#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000174 if (sb->s_flags & MS_POSIXACL)
175 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
176 ea_value, (const int)value_size,
177 ACL_TYPE_ACCESS, cifs_sb->local_nls,
178 cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700179 CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000180 cFYI(1, "set POSIX ACL rc %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000182 cFYI(1, "set POSIX ACL not supported");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183#endif
Steve French79a58d12007-07-06 22:44:50 +0000184 } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
185 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000187 if (sb->s_flags & MS_POSIXACL)
188 rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
189 ea_value, (const int)value_size,
Steve French737b7582005-04-28 22:41:06 -0700190 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
Steve French79a58d12007-07-06 22:44:50 +0000191 cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700192 CIFS_MOUNT_MAP_SPECIAL_CHR);
Joe Perchesb6b38f72010-04-21 03:50:45 +0000193 cFYI(1, "set POSIX default ACL rc %d", rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000195 cFYI(1, "set default POSIX ACL not supported");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196#endif
197 } else {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000198 cFYI(1, "illegal xattr request %s (only user namespace"
199 " supported)", ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 /* BB what if no namespace prefix? */
Steve French79a58d12007-07-06 22:44:50 +0000201 /* Should we just pass them to server, except for
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 system and perhaps security prefixes? */
203 }
204 }
205
206set_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800207 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400209 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210#endif
211 return rc;
212}
213
Steve French79a58d12007-07-06 22:44:50 +0000214ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
215 void *ea_value, size_t buf_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216{
217 ssize_t rc = -EOPNOTSUPP;
218#ifdef CONFIG_CIFS_XATTR
219 int xid;
220 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -0400221 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 struct cifsTconInfo *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000223 struct super_block *sb;
224 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Steve French79a58d12007-07-06 22:44:50 +0000226 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 return -EIO;
Steve French79a58d12007-07-06 22:44:50 +0000228 if (direntry->d_inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 return -EIO;
230 sb = direntry->d_inode->i_sb;
Steve French79a58d12007-07-06 22:44:50 +0000231 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 return -EIO;
233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 cifs_sb = CIFS_SB(sb);
Jeff Layton7ffec372010-09-29 19:51:11 -0400235 tlink = cifs_sb_tlink(cifs_sb);
236 if (IS_ERR(tlink))
237 return PTR_ERR(tlink);
238 pTcon = tlink_tcon(tlink);
239
240 xid = GetXid();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000243 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530244 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400245 goto get_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 }
247 /* return dos attributes as pseudo xattr */
248 /* return alt name if available as pseudo attr */
Steve French79a58d12007-07-06 22:44:50 +0000249 if (ea_name == NULL) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000250 cFYI(1, "Null xattr names not supported");
Steve French79a58d12007-07-06 22:44:50 +0000251 } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) {
252 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 goto get_ea_exit;
254
Steve French79a58d12007-07-06 22:44:50 +0000255 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000256 cFYI(1, "attempt to query cifs inode metadata");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 /* revalidate/getattr then populate from inode */
258 } /* BB add else when above is implemented */
259 ea_name += 5; /* skip past user. prefix */
Jeff Layton31c05192010-02-10 16:18:26 -0500260 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
Steve French737b7582005-04-28 22:41:06 -0700261 buf_size, cifs_sb->local_nls,
262 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French79a58d12007-07-06 22:44:50 +0000263 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) {
264 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 goto get_ea_exit;
266
267 ea_name += 4; /* skip past os2. prefix */
Jeff Layton31c05192010-02-10 16:18:26 -0500268 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
Steve French737b7582005-04-28 22:41:06 -0700269 buf_size, cifs_sb->local_nls,
270 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French79a58d12007-07-06 22:44:50 +0000271 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
Steve French0a4b92c2006-01-12 15:44:21 -0800272 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000274 if (sb->s_flags & MS_POSIXACL)
Steve French1da0c782005-04-28 22:41:04 -0700275 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Steve French79a58d12007-07-06 22:44:50 +0000276 ea_value, buf_size, ACL_TYPE_ACCESS,
Steve French737b7582005-04-28 22:41:06 -0700277 cifs_sb->local_nls,
Steve French79a58d12007-07-06 22:44:50 +0000278 cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700279 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve Frenchd12fd122007-10-03 19:43:19 +0000280#ifdef CONFIG_CIFS_EXPERIMENTAL
Steve Frenchad7a2922008-02-07 23:25:02 +0000281 else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
Steve French0a4b92c2006-01-12 15:44:21 -0800282 __u16 fid;
Steve French4b18f2a2008-04-29 00:06:05 +0000283 int oplock = 0;
Steve French630f3f02007-10-25 21:17:17 +0000284 struct cifs_ntsd *pacl = NULL;
285 __u32 buflen = 0;
Steve French63d25832007-11-05 21:46:10 +0000286 if (experimEnabled)
Steve Frenchd12fd122007-10-03 19:43:19 +0000287 rc = CIFSSMBOpen(xid, pTcon, full_path,
288 FILE_OPEN, GENERIC_READ, 0, &fid,
289 &oplock, NULL, cifs_sb->local_nls,
290 cifs_sb->mnt_cifs_flags &
291 CIFS_MOUNT_MAP_SPECIAL_CHR);
292 /* else rc is EOPNOTSUPP from above */
293
Steve French63d25832007-11-05 21:46:10 +0000294 if (rc == 0) {
Steve French630f3f02007-10-25 21:17:17 +0000295 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl,
296 &buflen);
Steve French2fe87f02006-09-21 07:02:52 +0000297 CIFSSMBClose(xid, pTcon, fid);
Steve French0a4b92c2006-01-12 15:44:21 -0800298 }
Steve Frenchd12fd122007-10-03 19:43:19 +0000299 }
300#endif /* EXPERIMENTAL */
Steve French79a58d12007-07-06 22:44:50 +0000301#else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000302 cFYI(1, "query POSIX ACL not supported yet");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303#endif /* CONFIG_CIFS_POSIX */
Steve French79a58d12007-07-06 22:44:50 +0000304 } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
Steve French0a4b92c2006-01-12 15:44:21 -0800305 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306#ifdef CONFIG_CIFS_POSIX
Steve French79a58d12007-07-06 22:44:50 +0000307 if (sb->s_flags & MS_POSIXACL)
Steve French1da0c782005-04-28 22:41:04 -0700308 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Steve French79a58d12007-07-06 22:44:50 +0000309 ea_value, buf_size, ACL_TYPE_DEFAULT,
Steve French737b7582005-04-28 22:41:06 -0700310 cifs_sb->local_nls,
Steve French79a58d12007-07-06 22:44:50 +0000311 cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700312 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French79a58d12007-07-06 22:44:50 +0000313#else
Joe Perchesb6b38f72010-04-21 03:50:45 +0000314 cFYI(1, "query POSIX default ACL not supported yet");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315#endif
Steve French79a58d12007-07-06 22:44:50 +0000316 } else if (strncmp(ea_name,
317 CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000318 cFYI(1, "Trusted xattr namespace not supported yet");
Steve French79a58d12007-07-06 22:44:50 +0000319 } else if (strncmp(ea_name,
320 CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
Joe Perchesb6b38f72010-04-21 03:50:45 +0000321 cFYI(1, "Security xattr namespace not supported yet");
Steve Frenchad7a2922008-02-07 23:25:02 +0000322 } else
Steve French79a58d12007-07-06 22:44:50 +0000323 cFYI(1,
Joe Perchesb6b38f72010-04-21 03:50:45 +0000324 "illegal xattr request %s (only user namespace supported)",
325 ea_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Steve French79a58d12007-07-06 22:44:50 +0000327 /* We could add an additional check for streams ie
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000329 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 returns as xattrs */
331
Steve French79a58d12007-07-06 22:44:50 +0000332 if (rc == -EINVAL)
333 rc = -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335get_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800336 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400338 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339#endif
340 return rc;
341}
342
Steve French79a58d12007-07-06 22:44:50 +0000343ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344{
345 ssize_t rc = -EOPNOTSUPP;
346#ifdef CONFIG_CIFS_XATTR
347 int xid;
348 struct cifs_sb_info *cifs_sb;
Jeff Layton7ffec372010-09-29 19:51:11 -0400349 struct tcon_link *tlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 struct cifsTconInfo *pTcon;
Steve French79a58d12007-07-06 22:44:50 +0000351 struct super_block *sb;
352 char *full_path;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Steve French79a58d12007-07-06 22:44:50 +0000354 if (direntry == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 return -EIO;
Steve French79a58d12007-07-06 22:44:50 +0000356 if (direntry->d_inode == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 return -EIO;
358 sb = direntry->d_inode->i_sb;
Steve French79a58d12007-07-06 22:44:50 +0000359 if (sb == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
362 cifs_sb = CIFS_SB(sb);
Steve French79a58d12007-07-06 22:44:50 +0000363 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
Steve Frenchea4c07d2006-08-16 19:44:25 +0000364 return -EOPNOTSUPP;
365
Jeff Layton7ffec372010-09-29 19:51:11 -0400366 tlink = cifs_sb_tlink(cifs_sb);
367 if (IS_ERR(tlink))
368 return PTR_ERR(tlink);
369 pTcon = tlink_tcon(tlink);
370
Steve Frenchea4c07d2006-08-16 19:44:25 +0000371 xid = GetXid();
372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 full_path = build_path_from_dentry(direntry);
Steve French79a58d12007-07-06 22:44:50 +0000374 if (full_path == NULL) {
Suresh Jayaraman0f3bc092009-06-25 18:12:34 +0530375 rc = -ENOMEM;
Jeff Layton7ffec372010-09-29 19:51:11 -0400376 goto list_ea_exit;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 }
378 /* return dos attributes as pseudo xattr */
379 /* return alt name if available as pseudo attr */
380
381 /* if proc/fs/cifs/streamstoxattr is set then
Steve French79a58d12007-07-06 22:44:50 +0000382 search server for EAs or streams to
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 returns as xattrs */
Jeff Layton31c05192010-02-10 16:18:26 -0500384 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
385 buf_size, cifs_sb->local_nls,
Steve French79a58d12007-07-06 22:44:50 +0000386 cifs_sb->mnt_cifs_flags &
Steve French737b7582005-04-28 22:41:06 -0700387 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Jeff Layton7ffec372010-09-29 19:51:11 -0400389list_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800390 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 FreeXid(xid);
Jeff Layton7ffec372010-09-29 19:51:11 -0400392 cifs_put_tlink(tlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393#endif
394 return rc;
395}