diff options
Diffstat (limited to 'fs/cifs/xattr.c')
| -rw-r--r-- | fs/cifs/xattr.c | 453 |
1 files changed, 266 insertions, 187 deletions
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index c1e02eff1d2..5ac836a86b1 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -1,7 +1,7 @@ /* * fs/cifs/xattr.c * - * Copyright (c) International Business Machines Corp., 2003 + * Copyright (c) International Business Machines Corp., 2003, 2007 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -21,6 +21,8 @@ #include <linux/fs.h> #include <linux/posix_acl_xattr.h> +#include <linux/slab.h> +#include <linux/xattr.h> #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -29,325 +31,402 @@ #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 */ - +#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" +/* BB need to add server (Samba e.g) support for security and trusted prefix */ -int cifs_removexattr(struct dentry * direntry, const char * ea_name) +int cifs_removexattr(struct dentry *direntry, const char *ea_name) { int rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR - int xid; + unsigned int xid; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - struct super_block * sb; - char * full_path; - - if(direntry == NULL) + struct tcon_link *tlink; + struct cifs_tcon *pTcon; + struct super_block *sb; + char *full_path = NULL; + + if (direntry == NULL) return -EIO; - if(direntry->d_inode == NULL) + if (direntry->d_inode == NULL) return -EIO; sb = direntry->d_inode->i_sb; - if(sb == NULL) + if (sb == NULL) return -EIO; - xid = GetXid(); - + cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb->tcon; - - down(&sb->s_vfs_rename_sem); + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = get_xid(); + full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); - if(full_path == NULL) { - FreeXid(xid); - return -ENOMEM; + if (full_path == NULL) { + rc = -ENOMEM; + goto remove_ea_exit; } - if(ea_name == NULL) { - cFYI(1,("Null xattr names not supported")); - } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) - && (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) { - cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name)); + if (ea_name == NULL) { + cifs_dbg(FYI, "Null xattr names not supported\n"); + } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) + && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) { + cifs_dbg(FYI, + "illegal xattr request %s (only user namespace supported)\n", + ea_name); /* BB what if no namespace prefix? */ /* Should we just pass them to server, except for system and perhaps security prefixes? */ } else { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto remove_ea_exit; - ea_name+=5; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL, - (__u16)0, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, NULL, (__u16)0, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } remove_ea_exit: - if (full_path) - kfree(full_path); - FreeXid(xid); + kfree(full_path); + free_xid(xid); + cifs_put_tlink(tlink); #endif return rc; } -int cifs_setxattr(struct dentry * direntry, const char * ea_name, - const void * ea_value, size_t value_size, int flags) +int cifs_setxattr(struct dentry *direntry, const char *ea_name, + const void *ea_value, size_t value_size, int flags) { int rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR - int xid; + unsigned int xid; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - struct super_block * sb; - char * full_path; + struct tcon_link *tlink; + struct cifs_tcon *pTcon; + struct super_block *sb; + char *full_path; - if(direntry == NULL) + if (direntry == NULL) return -EIO; - if(direntry->d_inode == NULL) + if (direntry->d_inode == NULL) return -EIO; sb = direntry->d_inode->i_sb; - if(sb == NULL) + if (sb == NULL) return -EIO; - xid = GetXid(); cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb->tcon; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = get_xid(); - down(&sb->s_vfs_rename_sem); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); - if(full_path == NULL) { - FreeXid(xid); - return -ENOMEM; + if (full_path == NULL) { + rc = -ENOMEM; + goto set_ea_exit; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ /* if proc/fs/cifs/streamstoxattr is set then - search server for EAs or streams to + search server for EAs or streams to returns as xattrs */ - if(value_size > MAX_EA_VALUE_SIZE) { - cFYI(1,("size of EA value too large")); - if(full_path) - kfree(full_path); - FreeXid(xid); - return -EOPNOTSUPP; + if (value_size > MAX_EA_VALUE_SIZE) { + cifs_dbg(FYI, "size of EA value too large\n"); + rc = -EOPNOTSUPP; + goto set_ea_exit; } - if(ea_name == NULL) { - cFYI(1,("Null xattr names not supported")); - } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + if (ea_name == NULL) { + cifs_dbg(FYI, "Null xattr names not supported\n"); + } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) + == 0) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; - if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) { - cFYI(1,("attempt to set cifs inode metadata")); - } - ea_name += 5; /* skip past user. prefix */ - rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, - (__u16)value_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) + cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); + + ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, ea_value, (__u16)value_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) + == 0) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; - ea_name += 4; /* skip past os2. prefix */ - rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, - (__u16)value_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ + if (pTcon->ses->server->ops->set_EA) + rc = pTcon->ses->server->ops->set_EA(xid, pTcon, + full_path, ea_name, ea_value, (__u16)value_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, + strlen(CIFS_XATTR_CIFS_ACL)) == 0) { +#ifdef CONFIG_CIFS_ACL + struct cifs_ntsd *pacl; + pacl = kmalloc(value_size, GFP_KERNEL); + if (!pacl) { + rc = -ENOMEM; + } else { + memcpy(pacl, ea_value, value_size); + if (pTcon->ses->server->ops->set_acl) + rc = pTcon->ses->server->ops->set_acl(pacl, + value_size, direntry->d_inode, + full_path, CIFS_ACL_DACL); + else + rc = -EOPNOTSUPP; + if (rc == 0) /* force revalidate of the inode */ + CIFS_I(direntry->d_inode)->time = 0; + kfree(pacl); + } +#else + cifs_dbg(FYI, "Set CIFS ACL not supported yet\n"); +#endif /* CONFIG_CIFS_ACL */ } else { - int temp; - temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, + int temp; + temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, strlen(POSIX_ACL_XATTR_ACCESS)); if (temp == 0) { #ifdef CONFIG_CIFS_POSIX - 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 & + 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 & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1,("set POSIX ACL rc %d",rc)); + cifs_dbg(FYI, "set POSIX ACL rc %d\n", rc); #else - cFYI(1,("set POSIX ACL not supported")); + cifs_dbg(FYI, "set POSIX ACL not supported\n"); #endif - } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { + } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, + strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { #ifdef CONFIG_CIFS_POSIX - if(sb->s_flags & MS_POSIXACL) - rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, - ea_value, (const int)value_size, + if (sb->s_flags & MS_POSIXACL) + rc = CIFSSMBSetPosixACL(xid, pTcon, full_path, + ea_value, (const int)value_size, ACL_TYPE_DEFAULT, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1,("set POSIX default ACL rc %d",rc)); + cifs_dbg(FYI, "set POSIX default ACL rc %d\n", rc); #else - cFYI(1,("set default POSIX ACL not supported")); + cifs_dbg(FYI, "set default POSIX ACL not supported\n"); #endif } else { - cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name)); + cifs_dbg(FYI, "illegal xattr request %s (only user namespace supported)\n", + ea_name); /* BB what if no namespace prefix? */ - /* Should we just pass them to server, except for + /* Should we just pass them to server, except for system and perhaps security prefixes? */ } } set_ea_exit: - if (full_path) - kfree(full_path); - FreeXid(xid); + kfree(full_path); + free_xid(xid); + cifs_put_tlink(tlink); #endif return rc; } -ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, - void * ea_value, size_t buf_size) +ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, + void *ea_value, size_t buf_size) { ssize_t rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR - int xid; + unsigned int xid; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - struct super_block * sb; - char * full_path; + struct tcon_link *tlink; + struct cifs_tcon *pTcon; + struct super_block *sb; + char *full_path; - if(direntry == NULL) + if (direntry == NULL) return -EIO; - if(direntry->d_inode == NULL) + if (direntry->d_inode == NULL) return -EIO; sb = direntry->d_inode->i_sb; - if(sb == NULL) + if (sb == NULL) return -EIO; - xid = GetXid(); - cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb->tcon; + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = get_xid(); - down(&sb->s_vfs_rename_sem); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); - if(full_path == NULL) { - FreeXid(xid); - return -ENOMEM; + if (full_path == NULL) { + rc = -ENOMEM; + goto get_ea_exit; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ - if(ea_name == NULL) { - cFYI(1,("Null xattr names not supported")); - } else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + if (ea_name == NULL) { + cifs_dbg(FYI, "Null xattr names not supported\n"); + } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) + == 0) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; - if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) { - cFYI(1,("attempt to query cifs inode metadata")); + if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) { + cifs_dbg(FYI, "attempt to query cifs inode metadata\n"); /* revalidate/getattr then populate from inode */ } /* BB add else when above is implemented */ - ea_name += 5; /* skip past user. prefix */ - rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ + if (pTcon->ses->server->ops->query_all_EAs) + rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, + full_path, ea_name, ea_value, buf_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; - ea_name += 4; /* skip past os2. prefix */ - rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, - buf_size, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { + ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ + if (pTcon->ses->server->ops->query_all_EAs) + rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, + full_path, ea_name, ea_value, buf_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); + } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, + strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { #ifdef CONFIG_CIFS_POSIX - if(sb->s_flags & MS_POSIXACL) + if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, - ea_value, buf_size, ACL_TYPE_ACCESS, + ea_value, buf_size, ACL_TYPE_ACCESS, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -#else - cFYI(1,("query POSIX ACL not supported yet")); +#else + cifs_dbg(FYI, "Query POSIX ACL not supported yet\n"); #endif /* CONFIG_CIFS_POSIX */ - } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { + } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, + strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { #ifdef CONFIG_CIFS_POSIX - if(sb->s_flags & MS_POSIXACL) + if (sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, - ea_value, buf_size, ACL_TYPE_DEFAULT, + ea_value, buf_size, ACL_TYPE_DEFAULT, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); -#else - cFYI(1,("query POSIX default ACL not supported yet")); -#endif - } else if(strncmp(ea_name, - CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) { - cFYI(1,("Trusted xattr namespace not supported yet")); - } else if(strncmp(ea_name, - CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) { - cFYI(1,("Security xattr namespace not supported yet")); - } else { - cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name)); - } +#else + cifs_dbg(FYI, "Query POSIX default ACL not supported yet\n"); +#endif /* CONFIG_CIFS_POSIX */ + } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, + strlen(CIFS_XATTR_CIFS_ACL)) == 0) { +#ifdef CONFIG_CIFS_ACL + u32 acllen; + struct cifs_ntsd *pacl; + + if (pTcon->ses->server->ops->get_acl == NULL) + goto get_ea_exit; /* rc already EOPNOTSUPP */ - /* We could add an additional check for streams ie + pacl = pTcon->ses->server->ops->get_acl(cifs_sb, + direntry->d_inode, full_path, &acllen); + if (IS_ERR(pacl)) { + rc = PTR_ERR(pacl); + cifs_dbg(VFS, "%s: error %zd getting sec desc\n", + __func__, rc); + } else { + if (ea_value) { + if (acllen > buf_size) + acllen = -ERANGE; + else + memcpy(ea_value, pacl, acllen); + } + rc = acllen; + kfree(pacl); + } +#else + cifs_dbg(FYI, "Query CIFS ACL not supported yet\n"); +#endif /* CONFIG_CIFS_ACL */ + } else if (strncmp(ea_name, + XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { + cifs_dbg(FYI, "Trusted xattr namespace not supported yet\n"); + } else if (strncmp(ea_name, + XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { + cifs_dbg(FYI, "Security xattr namespace not supported yet\n"); + } else + cifs_dbg(FYI, + "illegal xattr request %s (only user namespace supported)\n", + ea_name); + + /* We could add an additional check for streams ie if proc/fs/cifs/streamstoxattr is set then - search server for EAs or streams to + search server for EAs or streams to returns as xattrs */ - if(rc == -EINVAL) - rc = -EOPNOTSUPP; + if (rc == -EINVAL) + rc = -EOPNOTSUPP; get_ea_exit: - if (full_path) - kfree(full_path); - FreeXid(xid); + kfree(full_path); + free_xid(xid); + cifs_put_tlink(tlink); #endif return rc; } -ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) +ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) { ssize_t rc = -EOPNOTSUPP; #ifdef CONFIG_CIFS_XATTR - int xid; + unsigned int xid; struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - struct super_block * sb; - char * full_path; + struct tcon_link *tlink; + struct cifs_tcon *pTcon; + struct super_block *sb; + char *full_path; - if(direntry == NULL) + if (direntry == NULL) return -EIO; - if(direntry->d_inode == NULL) + if (direntry->d_inode == NULL) return -EIO; sb = direntry->d_inode->i_sb; - if(sb == NULL) + if (sb == NULL) return -EIO; - xid = GetXid(); cifs_sb = CIFS_SB(sb); - pTcon = cifs_sb->tcon; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) + return -EOPNOTSUPP; + + tlink = cifs_sb_tlink(cifs_sb); + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + pTcon = tlink_tcon(tlink); + + xid = get_xid(); - down(&sb->s_vfs_rename_sem); full_path = build_path_from_dentry(direntry); - up(&sb->s_vfs_rename_sem); - if(full_path == NULL) { - FreeXid(xid); - return -ENOMEM; + if (full_path == NULL) { + rc = -ENOMEM; + goto list_ea_exit; } /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ /* if proc/fs/cifs/streamstoxattr is set then - search server for EAs or streams to + search server for EAs or streams to returns as xattrs */ - rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & - CIFS_MOUNT_MAP_SPECIAL_CHR); - if (full_path) - kfree(full_path); - FreeXid(xid); + if (pTcon->ses->server->ops->query_all_EAs) + rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon, + full_path, NULL, data, buf_size, + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); +list_ea_exit: + kfree(full_path); + free_xid(xid); + cifs_put_tlink(tlink); #endif return rc; } |
