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