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