blob: 18fcec190f8b5c6e4fdb6f5856ed114a473a411e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
22#include <linux/fs.h>
23#include <linux/posix_acl_xattr.h>
24#include "cifsfs.h"
25#include "cifspdu.h"
26#include "cifsglob.h"
27#include "cifsproto.h"
28#include "cifs_debug.h"
29
30#define MAX_EA_VALUE_SIZE 65535
31#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
32#define CIFS_XATTR_USER_PREFIX "user."
33#define CIFS_XATTR_SYSTEM_PREFIX "system."
34#define CIFS_XATTR_OS2_PREFIX "os2."
35#define CIFS_XATTR_SECURITY_PREFIX ".security"
36#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
37#define XATTR_TRUSTED_PREFIX_LEN 8
38#define XATTR_SECURITY_PREFIX_LEN 9
39/* BB need to add server (Samba e.g) support for security and trusted prefix */
40
41
42
43int cifs_removexattr(struct dentry * direntry, const char * ea_name)
44{
45 int rc = -EOPNOTSUPP;
46#ifdef CONFIG_CIFS_XATTR
47 int xid;
48 struct cifs_sb_info *cifs_sb;
49 struct cifsTconInfo *pTcon;
50 struct super_block * sb;
51 char * full_path;
52
53 if(direntry == NULL)
54 return -EIO;
55 if(direntry->d_inode == NULL)
56 return -EIO;
57 sb = direntry->d_inode->i_sb;
58 if(sb == NULL)
59 return -EIO;
60 xid = GetXid();
61
62 cifs_sb = CIFS_SB(sb);
63 pTcon = cifs_sb->tcon;
64
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 if(full_path == NULL) {
67 FreeXid(xid);
68 return -ENOMEM;
69 }
70 if(ea_name == NULL) {
71 cFYI(1,("Null xattr names not supported"));
72 } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
73 && (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
74 cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
75 /* BB what if no namespace prefix? */
76 /* Should we just pass them to server, except for
77 system and perhaps security prefixes? */
78 } else {
79 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
80 goto remove_ea_exit;
81
82 ea_name+=5; /* skip past user. prefix */
83 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
Steve French737b7582005-04-28 22:41:06 -070084 (__u16)0, cifs_sb->local_nls,
85 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 }
87remove_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -080088 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 FreeXid(xid);
90#endif
91 return rc;
92}
93
94int cifs_setxattr(struct dentry * direntry, const char * ea_name,
95 const void * ea_value, size_t value_size, int flags)
96{
97 int rc = -EOPNOTSUPP;
98#ifdef CONFIG_CIFS_XATTR
99 int xid;
100 struct cifs_sb_info *cifs_sb;
101 struct cifsTconInfo *pTcon;
102 struct super_block * sb;
103 char * full_path;
104
105 if(direntry == NULL)
106 return -EIO;
107 if(direntry->d_inode == NULL)
108 return -EIO;
109 sb = direntry->d_inode->i_sb;
110 if(sb == NULL)
111 return -EIO;
112 xid = GetXid();
113
114 cifs_sb = CIFS_SB(sb);
115 pTcon = cifs_sb->tcon;
116
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 if(full_path == NULL) {
119 FreeXid(xid);
120 return -ENOMEM;
121 }
122 /* return dos attributes as pseudo xattr */
123 /* return alt name if available as pseudo attr */
124
125 /* if proc/fs/cifs/streamstoxattr is set then
126 search server for EAs or streams to
127 returns as xattrs */
128 if(value_size > MAX_EA_VALUE_SIZE) {
129 cFYI(1,("size of EA value too large"));
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800130 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 FreeXid(xid);
132 return -EOPNOTSUPP;
133 }
134
135 if(ea_name == NULL) {
136 cFYI(1,("Null xattr names not supported"));
137 } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
138 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
139 goto set_ea_exit;
140 if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
141 cFYI(1,("attempt to set cifs inode metadata"));
142 }
143 ea_name += 5; /* skip past user. prefix */
144 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
Steve French737b7582005-04-28 22:41:06 -0700145 (__u16)value_size, cifs_sb->local_nls,
146 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
148 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
149 goto set_ea_exit;
150
151 ea_name += 4; /* skip past os2. prefix */
152 rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
Steve French737b7582005-04-28 22:41:06 -0700153 (__u16)value_size, cifs_sb->local_nls,
154 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 } else {
156 int temp;
157 temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
158 strlen(POSIX_ACL_XATTR_ACCESS));
159 if (temp == 0) {
160#ifdef CONFIG_CIFS_POSIX
Steve French1da0c782005-04-28 22:41:04 -0700161 if(sb->s_flags & MS_POSIXACL)
162 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
163 ea_value, (const int)value_size,
Steve French737b7582005-04-28 22:41:06 -0700164 ACL_TYPE_ACCESS,cifs_sb->local_nls,
165 cifs_sb->mnt_cifs_flags &
166 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 cFYI(1,("set POSIX ACL rc %d",rc));
168#else
169 cFYI(1,("set POSIX ACL not supported"));
170#endif
171 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
172#ifdef CONFIG_CIFS_POSIX
Steve French1da0c782005-04-28 22:41:04 -0700173 if(sb->s_flags & MS_POSIXACL)
174 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,
175 ea_value, (const int)value_size,
Steve French737b7582005-04-28 22:41:06 -0700176 ACL_TYPE_DEFAULT, cifs_sb->local_nls,
177 cifs_sb->mnt_cifs_flags &
178 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 cFYI(1,("set POSIX default ACL rc %d",rc));
180#else
181 cFYI(1,("set default POSIX ACL not supported"));
182#endif
183 } else {
184 cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
185 /* BB what if no namespace prefix? */
186 /* Should we just pass them to server, except for
187 system and perhaps security prefixes? */
188 }
189 }
190
191set_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800192 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 FreeXid(xid);
194#endif
195 return rc;
196}
197
198ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
199 void * ea_value, size_t buf_size)
200{
201 ssize_t rc = -EOPNOTSUPP;
202#ifdef CONFIG_CIFS_XATTR
203 int xid;
204 struct cifs_sb_info *cifs_sb;
205 struct cifsTconInfo *pTcon;
206 struct super_block * sb;
207 char * full_path;
208
209 if(direntry == NULL)
210 return -EIO;
211 if(direntry->d_inode == NULL)
212 return -EIO;
213 sb = direntry->d_inode->i_sb;
214 if(sb == NULL)
215 return -EIO;
216
217 xid = GetXid();
218
219 cifs_sb = CIFS_SB(sb);
220 pTcon = cifs_sb->tcon;
221
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 if(full_path == NULL) {
224 FreeXid(xid);
225 return -ENOMEM;
226 }
227 /* return dos attributes as pseudo xattr */
228 /* return alt name if available as pseudo attr */
229 if(ea_name == NULL) {
230 cFYI(1,("Null xattr names not supported"));
231 } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
232 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
233 goto get_ea_exit;
234
235 if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
236 cFYI(1,("attempt to query cifs inode metadata"));
237 /* revalidate/getattr then populate from inode */
238 } /* BB add else when above is implemented */
239 ea_name += 5; /* skip past user. prefix */
240 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
Steve French737b7582005-04-28 22:41:06 -0700241 buf_size, cifs_sb->local_nls,
242 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
244 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
245 goto get_ea_exit;
246
247 ea_name += 4; /* skip past os2. prefix */
248 rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
Steve French737b7582005-04-28 22:41:06 -0700249 buf_size, cifs_sb->local_nls,
250 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French0a4b92c2006-01-12 15:44:21 -0800251 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
252 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253#ifdef CONFIG_CIFS_POSIX
Steve French1da0c782005-04-28 22:41:04 -0700254 if(sb->s_flags & MS_POSIXACL)
255 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 ea_value, buf_size, ACL_TYPE_ACCESS,
Steve French737b7582005-04-28 22:41:06 -0700257 cifs_sb->local_nls,
258 cifs_sb->mnt_cifs_flags &
259 CIFS_MOUNT_MAP_SPECIAL_CHR);
Steve French0a4b92c2006-01-12 15:44:21 -0800260/* else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
261 __u16 fid;
262 int oplock = FALSE;
263 rc = CIFSSMBOpen(xid, pTcon, full_path,
264 FILE_OPEN, GENERIC_READ, 0, &fid,
265 &oplock, NULL, cifs_sb->local_nls,
266 cifs_sb->mnt_cifs_flags &
267 CIFS_MOUNT_MAP_SPECIAL_CHR);
268 if(rc == 0) {
269 rc = CIFSSMBGetCIFSACL(xid, pTcon, fid,
270 ea_value, buf_size,
271 ACL_TYPE_ACCESS);
Steve French2fe87f02006-09-21 07:02:52 +0000272 CIFSSMBClose(xid, pTcon, fid);
Steve French0a4b92c2006-01-12 15:44:21 -0800273 }
274 } */ /* BB enable after fixing up return data */
275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276#else
277 cFYI(1,("query POSIX ACL not supported yet"));
278#endif /* CONFIG_CIFS_POSIX */
Steve French0a4b92c2006-01-12 15:44:21 -0800279 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,
280 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281#ifdef CONFIG_CIFS_POSIX
Steve French1da0c782005-04-28 22:41:04 -0700282 if(sb->s_flags & MS_POSIXACL)
283 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 ea_value, buf_size, ACL_TYPE_DEFAULT,
Steve French737b7582005-04-28 22:41:06 -0700285 cifs_sb->local_nls,
286 cifs_sb->mnt_cifs_flags &
287 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288#else
289 cFYI(1,("query POSIX default ACL not supported yet"));
290#endif
291 } else if(strncmp(ea_name,
292 CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
293 cFYI(1,("Trusted xattr namespace not supported yet"));
294 } else if(strncmp(ea_name,
295 CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
296 cFYI(1,("Security xattr namespace not supported yet"));
297 } else {
298 cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
299 }
300
301 /* We could add an additional check for streams ie
302 if proc/fs/cifs/streamstoxattr is set then
303 search server for EAs or streams to
304 returns as xattrs */
305
306 if(rc == -EINVAL)
307 rc = -EOPNOTSUPP;
308
309get_ea_exit:
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800310 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 FreeXid(xid);
312#endif
313 return rc;
314}
315
316ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
317{
318 ssize_t rc = -EOPNOTSUPP;
319#ifdef CONFIG_CIFS_XATTR
320 int xid;
321 struct cifs_sb_info *cifs_sb;
322 struct cifsTconInfo *pTcon;
323 struct super_block * sb;
324 char * full_path;
325
326 if(direntry == NULL)
327 return -EIO;
328 if(direntry->d_inode == NULL)
329 return -EIO;
330 sb = direntry->d_inode->i_sb;
331 if(sb == NULL)
332 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 cifs_sb = CIFS_SB(sb);
335 pTcon = cifs_sb->tcon;
336
Steve Frenchea4c07d2006-08-16 19:44:25 +0000337 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
338 return -EOPNOTSUPP;
339
340 xid = GetXid();
341
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 full_path = build_path_from_dentry(direntry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 if(full_path == NULL) {
344 FreeXid(xid);
345 return -ENOMEM;
346 }
347 /* return dos attributes as pseudo xattr */
348 /* return alt name if available as pseudo attr */
349
350 /* if proc/fs/cifs/streamstoxattr is set then
351 search server for EAs or streams to
352 returns as xattrs */
353 rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
Steve French737b7582005-04-28 22:41:06 -0700354 cifs_sb->local_nls,
355 cifs_sb->mnt_cifs_flags &
356 CIFS_MOUNT_MAP_SPECIAL_CHR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Jesper Juhlf99d49a2005-11-07 01:01:34 -0800358 kfree(full_path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 FreeXid(xid);
360#endif
361 return rc;
362}