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 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 65 full_path = build_path_from_dentry(direntry); 66 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, 84 (__u16)0, cifs_sb->local_nls, 85 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 86 } 87remove_ea_exit: 88 kfree(full_path); 89 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 117 full_path = build_path_from_dentry(direntry); 118 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")); 130 kfree(full_path); 131 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, 145 (__u16)value_size, cifs_sb->local_nls, 146 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 147 } 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, 153 (__u16)value_size, cifs_sb->local_nls, 154 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 155 } 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 161 if(sb->s_flags & MS_POSIXACL) 162 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, 163 ea_value, (const int)value_size, 164 ACL_TYPE_ACCESS,cifs_sb->local_nls, 165 cifs_sb->mnt_cifs_flags & 166 CIFS_MOUNT_MAP_SPECIAL_CHR); 167 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 173 if(sb->s_flags & MS_POSIXACL) 174 rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, 175 ea_value, (const int)value_size, 176 ACL_TYPE_DEFAULT, cifs_sb->local_nls, 177 cifs_sb->mnt_cifs_flags & 178 CIFS_MOUNT_MAP_SPECIAL_CHR); 179 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: 192 kfree(full_path); 193 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 222 full_path = build_path_from_dentry(direntry); 223 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, 241 buf_size, cifs_sb->local_nls, 242 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 243 } 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, 249 buf_size, cifs_sb->local_nls, 250 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 251 } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, 252 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { 253#ifdef CONFIG_CIFS_POSIX 254 if(sb->s_flags & MS_POSIXACL) 255 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 256 ea_value, buf_size, ACL_TYPE_ACCESS, 257 cifs_sb->local_nls, 258 cifs_sb->mnt_cifs_flags & 259 CIFS_MOUNT_MAP_SPECIAL_CHR); 260/* 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); 272 CIFSSMBClose(xid, pTcon, fid); 273 } 274 } */ /* BB enable after fixing up return data */ 275 276#else 277 cFYI(1,("query POSIX ACL not supported yet")); 278#endif /* CONFIG_CIFS_POSIX */ 279 } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT, 280 strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { 281#ifdef CONFIG_CIFS_POSIX 282 if(sb->s_flags & MS_POSIXACL) 283 rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, 284 ea_value, buf_size, ACL_TYPE_DEFAULT, 285 cifs_sb->local_nls, 286 cifs_sb->mnt_cifs_flags & 287 CIFS_MOUNT_MAP_SPECIAL_CHR); 288#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: 310 kfree(full_path); 311 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; 333 334 cifs_sb = CIFS_SB(sb); 335 pTcon = cifs_sb->tcon; 336 337 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 338 return -EOPNOTSUPP; 339 340 xid = GetXid(); 341 342 full_path = build_path_from_dentry(direntry); 343 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, 354 cifs_sb->local_nls, 355 cifs_sb->mnt_cifs_flags & 356 CIFS_MOUNT_MAP_SPECIAL_CHR); 357 358 kfree(full_path); 359 FreeXid(xid); 360#endif 361 return rc; 362} 363