bk://cifs.bkbits.net/linux-2.5cifs
cifs.adm@hostme.bitkeeper.com|ChangeSet|20040727181637|48812 cifs.adm

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/07/27 06:02:46-05:00 stevef@steveft21.ltcsamba 
#   [CIFS] xattr support part 4   add set EA support
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/xattr.c
#   2004/07/27 06:02:19-05:00 stevef@steveft21.ltcsamba +23 -4
#   add set EA support
# 
# fs/cifs/cifssmb.c
#   2004/07/27 06:02:18-05:00 stevef@steveft21.ltcsamba +109 -6
#   add set EA support and cleanup const parms for some prototypes
# 
# fs/cifs/cifsproto.h
#   2004/07/27 06:02:18-05:00 stevef@steveft21.ltcsamba +6 -2
#   add set EA support and cleanup const parms for some prototypes
# 
# fs/cifs/cifspdu.h
#   2004/07/27 06:02:18-05:00 stevef@steveft21.ltcsamba +2 -0
#   add set EA support 
# 
# ChangeSet
#   2004/07/26 16:58:23-05:00 stevef@steveft21.ltcsamba 
#   [CIFS] xattr support part 3 add query EA support to retrieve individual xattr values
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/xattr.c
#   2004/07/26 16:57:54-05:00 stevef@steveft21.ltcsamba +99 -6
#   [CIFS] xattr support part 3 add query EA
# 
# fs/cifs/cifssmb.c
#   2004/07/26 16:57:54-05:00 stevef@steveft21.ltcsamba +152 -0
#   [CIFS] xattr support part 3 add query EA
# 
# fs/cifs/cifsproto.h
#   2004/07/26 16:57:53-05:00 stevef@steveft21.ltcsamba +4 -0
#   [CIFS] xattr support part 3 add query EA prototype
# 
# ChangeSet
#   2004/07/24 09:42:08-05:00 stevef@steveft21.ltcsamba 
#   [CIFS] xattr suport part 2: add listxattr support
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/xattr.c
#   2004/07/24 09:41:15-05:00 stevef@steveft21.ltcsamba +4 -2
#   add cifs listxattr support
# 
# fs/cifs/cifssmb.c
#   2004/07/24 09:41:15-05:00 stevef@steveft21.ltcsamba +130 -3
#   add cifs listxattr support and level 1 setpathinfo
# 
# fs/cifs/cifsproto.h
#   2004/07/24 09:41:15-05:00 stevef@steveft21.ltcsamba +3 -4
#   add cifs listxattr support
# 
# fs/cifs/cifspdu.h
#   2004/07/24 09:41:15-05:00 stevef@steveft21.ltcsamba +17 -4
#   add level 1 setpathinfo
# 
# ChangeSet
#   2004/07/23 13:46:55-07:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Alpha not studly enough for SCH_CLK_CPU.
#   
#   The cycle counter it provides overflows very quickly,
#   on the order of 10 minutes, so it is not suitable for
#   this purpose.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# net/sched/Kconfig
#   2004/07/23 13:46:29-07:00 davem@nuts.davemloft.net +1 -2
#   [PKT_SCHED]: Alpha not studly enough for SCH_CLK_CPU.
#   
#   The cycle counter it provides overflows very quickly,
#   on the order of 10 minutes, so it is not suitable for
#   this purpose.
#   
#   Signed-off-by: David S. Miller <davem@redhat.com>
# 
# ChangeSet
#   2004/07/18 22:26:25-05:00 stevef@smfhome.smfdom 
#   [CIFS] remove unneeded, unused prototypes.  Suggested by Carl Spalletta
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/smbencrypt.c
#   2004/07/18 22:26:12-05:00 stevef@smfhome.smfdom +0 -2
#   remove unneeded, unused prototypes
# 
# fs/cifs/cifsproto.h
#   2004/07/18 22:26:12-05:00 stevef@smfhome.smfdom +0 -25
#   remove unneeded, unused prototypes
# 
# fs/cifs/cifsfs.h
#   2004/07/18 22:26:12-05:00 stevef@smfhome.smfdom +0 -4
#   remove unneeded, unused prototypes
# 
# ChangeSet
#   2004/07/18 17:23:42-05:00 stevef@smfhome.smfdom 
#   CIFS: Add missing mount option for optionally cifs perm checks when uids on server and client do not match and for optionally overriding 
#   server setting default uid/gid of new cifs files and directories.
#   
#   Signed-off-by: Steve French (sfrench@us.ibm.com)
# 
# fs/cifs/inode.c
#   2004/07/18 17:23:35-05:00 stevef@smfhome.smfdom +14 -6
#   Add missing mount option for cifs perm checks and uid setting.
# 
# fs/cifs/dir.c
#   2004/07/18 17:23:35-05:00 stevef@smfhome.smfdom +19 -4
#   Add missing mount option for cifs perm checks and uid setting.
# 
# fs/cifs/connect.c
#   2004/07/18 17:23:34-05:00 stevef@smfhome.smfdom +16 -0
#   Add missing mount option for cifs perm checks and uid setting.
# 
# fs/cifs/cifsfs.c
#   2004/07/18 17:23:34-05:00 stevef@smfhome.smfdom +3 -7
#   Add missing mount option for cifs perm checks and uid setting.
# 
# fs/cifs/cifs_fs_sb.h
#   2004/07/18 17:23:34-05:00 stevef@smfhome.smfdom +4 -0
#   Add missing mount option for cifs perm checks and uid setting.
# 
# fs/cifs/README
#   2004/07/18 17:23:34-05:00 stevef@smfhome.smfdom +27 -1
#   Add missing mount option for cifs perm checks and uid setting.
# 
# fs/cifs/CHANGES
#   2004/07/18 17:23:34-05:00 stevef@smfhome.smfdom +13 -0
#   Update cifs change log
# 
diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/CHANGES	2004-07-27 18:29:53 -07:00
@@ -1,3 +1,16 @@
+Version 1.21
+------------
+Add new mount parm to control whether mode check (vfs_permission) is done on
+the client.  If Unix extensions are enabled and the uids on the client
+and server do not match, client permission checks are meaningless on
+server uids that do not exist on the client (this does not affect the
+normal ACL check which occurs on the server).  Fix default uid
+on mknod to match create and mkdir. Add optional mount parm to allow
+override of the default uid behavior (in which the server sets the uid
+and gid of newly created files). Normally for network filesystem mounts
+user want the server to set the uid/gid on newly created files (rather than 
+using uid of the client processes you would in a local filesystem).
+
 Version 1.20
 ------------
 Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
diff -Nru a/fs/cifs/README b/fs/cifs/README
--- a/fs/cifs/README	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/README	2004-07-27 18:29:53 -07:00
@@ -255,7 +255,33 @@
 		mount helper will not prompt the user for a password
 		if guest is specified on the mount options.  If no
 		password is specified a null password will be used.
-
+  perm          Client does permission checks (vfs_permission check of uid
+		and gid of the file against the mode and desired operation),
+		Note that this is in addition to the normal ACL check on the
+		target machine done by the server software. 
+		Client permission checking is enabled by default.
+  noperm        Client does not do permission checks.  This can expose
+		files on this mount to access by other users on the local
+		client system. It is typically only needed when the server
+		supports the CIFS Unix Extensions but the UIDs/GIDs on the
+		client and server system do not match closely enough to allow
+		access by the user doing the mount.
+		Note that this does not affect the normal ACL check on the
+		target machine done by the server software (of the server
+		ACL against the user name provided at mount time).
+  setuids       If the CIFS Unix extensions are negotiated with the server
+		the client will attempt to set the effective uid and gid of
+		the local process on newly created files, directories, and
+		devices (create, mkdir, mknod).
+  nosetuids     The client will not attempt to set the uid and gid on
+		on newly created files, directories, and devices (create, 
+		mkdir, mknod) which will result in the server setting the
+		uid and gid to the default (usually the server uid of the
+		usern who mounted the share).  Letting the server (rather than
+		the client) set the uid and gid is the default. This
+		parameter has no effect if the CIFS Unix Extensions are not
+		negotiated.
+		
 The mount.cifs mount helper also accepts a few mount options before -o
 including:
 
diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
--- a/fs/cifs/cifs_fs_sb.h	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/cifs_fs_sb.h	2004-07-27 18:29:53 -07:00
@@ -18,6 +18,9 @@
 #ifndef _CIFS_FS_SB_H
 #define _CIFS_FS_SB_H
 
+#define CIFS_MOUNT_NO_PERM	1 /* do not do client vfs_perm check */
+#define CIFS_MOUNT_SET_UID      2 /* set current->euid in create etc. */
+
 struct cifs_sb_info {
 	struct cifsTconInfo *tcon;	/* primary mount */
 	struct list_head nested_tcon_q;
@@ -28,5 +31,6 @@
 	gid_t	mnt_gid;
 	mode_t	mnt_file_mode;
 	mode_t	mnt_dir_mode;
+	int     mnt_cifs_flags;
 };
 #endif				/* _CIFS_FS_SB_H */
diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
--- a/fs/cifs/cifsfs.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/cifsfs.c	2004-07-27 18:29:53 -07:00
@@ -192,15 +192,11 @@
 
 static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
 {
-        struct cifs_sb_info *cifs_sb;
+	struct cifs_sb_info *cifs_sb;
 
-        cifs_sb = CIFS_SB(inode->i_sb);
+	cifs_sb = CIFS_SB(inode->i_sb);
 
-        if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
-		/* the server supports the Unix-like mode bits and does its
-		own permission checks, and therefore we do not allow the file
-		mode to be overriden on these mounts - so do not do perm
-		check on client side */
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
 		return 0;
 	} else /* file mode might have been restricted at mount time 
 		on the client (above and beyond ACL on servers) for  
diff -Nru a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
--- a/fs/cifs/cifsfs.h	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/cifsfs.h	2004-07-27 18:29:53 -07:00
@@ -32,14 +32,10 @@
 #define TRUE 1
 #endif
 
-extern int map_cifs_error(int error_class, int error_code,
-			  int status_codes_negotiated);
-
 extern struct address_space_operations cifs_addr_ops;
 
 /* Functions related to super block operations */
 extern struct super_operations cifs_super_ops;
-extern void cifs_put_inode(struct inode *);
 extern void cifs_read_inode(struct inode *);
 extern void cifs_delete_inode(struct inode *);
 /* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
diff -Nru a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
--- a/fs/cifs/cifspdu.h	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/cifspdu.h	2004-07-27 18:29:53 -07:00
@@ -1046,6 +1046,8 @@
 
 /* PathInfo/FileInfo infolevels */
 #define SMB_INFO_STANDARD                   1
+#define SMB_SET_FILE_EA                     2
+#define SMB_QUERY_FILE_EA_SIZE              2
 #define SMB_INFO_QUERY_EAS_FROM_LIST        3
 #define SMB_INFO_QUERY_ALL_EAS              4
 #define SMB_INFO_IS_NAME_VALID              6
@@ -1620,6 +1622,19 @@
 	char LinkDest[1];
 } FILE_UNIX_LINK_INFO;		/* level 513 QPathInfo */
 
+typedef struct {
+	__u16 CreationDate;
+	__u16 CreationTime;
+	__u16 LastAccessDate;
+	__u16 LastAccessTime;
+	__u16 LastWriteDate;
+	__u16 LastWriteTime;
+	__u32 DataSize; /* File Size (EOF) */
+	__u32 AllocationSize;
+	__u16 Attributes; /* verify not u32 */
+	__u32 EASize;
+} FILE_INFO_STANDARD;  /* level 1 SetPath/FileInfo */
+
 /* defines for enumerating possible values of the Unix type field below */
 #define UNIX_FILE      0
 #define UNIX_DIR       1
@@ -1680,12 +1695,12 @@
 } FILE_DIRECTORY_INFO;   /* level 257 FF response data area */
 
 struct gea {
-	unsigned char cbName;
-	char szName[1];
+	unsigned char name_len;
+	char name[1];
 };
 
 struct gealist {
-	unsigned long cbList;
+	unsigned long list_len;
 	struct gea list[1];
 };
 
@@ -1693,7 +1708,7 @@
 	unsigned char EA_flags;
 	__u8 name_len;
 	__u16 value_len;
-	char szName[1];
+	char name[1];
 	/* optionally followed by value */
 };
 /* flags for _FEA.fEA */
diff -Nru a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
--- a/fs/cifs/cifsproto.h	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/cifsproto.h	2004-07-27 18:29:53 -07:00
@@ -128,10 +128,10 @@
 			const struct nls_table *nls_codepage);
 
 extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
-			char *fileName, FILE_BASIC_INFO * data,
+			const char *fileName, const FILE_BASIC_INFO * data,
 			const struct nls_table *nls_codepage);
 extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
-			char *fileName, __u64 size,int setAllocationSizeFlag,
+			const char *fileName, __u64 size,int setAllocationSizeFlag,
 			const struct nls_table *nls_codepage);
 extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
 			 __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
@@ -213,31 +213,6 @@
 extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
 extern void CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
 extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
-
-extern int CIFSBuildServerList(int xid, char *serverBufferList,
-			int recordlength, int *entries,
-			int *totalEntries, int *topoChangedFlag);
-extern int CIFSSMBQueryShares(int xid, struct cifsTconInfo *tcon,
-			struct shareInfo *shareList, int bufferLen,
-			int *entries, int *totalEntries);
-extern int CIFSSMBQueryAlias(int xid, struct cifsTconInfo *tcon,
-			struct aliasInfo *aliasList, int bufferLen,
-			int *entries, int *totalEntries);
-extern int CIFSSMBAliasInfo(int xid, struct cifsTconInfo *tcon,
-			char *aliasName, char *serverName,
-			char *shareName, char *comment);
-extern int CIFSSMBGetShareInfo(int xid, struct cifsTconInfo *tcon,
-			char *share, char *comment);
-extern int CIFSSMBGetUserPerms(int xid, struct cifsTconInfo *tcon,
-			char *userName, char *searchName, int *perms);
-extern int CIFSSMBSync(int xid, struct cifsTconInfo *tcon, int netfid, int pid);
-
-extern int CIFSSMBSeek(int xid,
-			struct cifsTconInfo *tcon,
-			int netfid,
-			int pid,
-			int whence, unsigned long offset, long long *newoffset);
-
 extern int CIFSSMBCopy(int xid,
 			struct cifsTconInfo *source_tcon,
 			const char *fromName,
@@ -247,8 +222,15 @@
 extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
 			const int notify_subdirs,const __u16 netfid,__u32 filter,
 			const struct nls_table *nls_codepage);
-extern int CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
-		 const unsigned char *searchName,
-		 char * EAData, size_t size,
-		 const struct nls_table *nls_codepage);
+extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+			const unsigned char *searchName, char * EAData,
+			size_t bufsize, const struct nls_table *nls_codepage);
+extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
+		const unsigned char * searchName,const unsigned char * ea_name,
+		unsigned char * ea_value, size_t buf_size, 
+		const struct nls_table *nls_codepage);
+extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 
+		const char *fileName, const char * ea_name, 
+		const void * ea_value, const __u16 ea_value_len, 
+		const struct nls_table *nls_codepage);
 #endif			/* _CIFSPROTO_H */
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/cifssmb.c	2004-07-27 18:29:53 -07:00
@@ -2287,7 +2287,7 @@
 }
 
 int
-CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
+CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
 			const struct nls_table *nls_codepage)
 {
 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
@@ -2359,7 +2359,7 @@
 }
 
 int
-CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
+CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
 		     const struct nls_table *nls_codepage)
 {
 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
@@ -2432,7 +2432,7 @@
 }
 
 int
-CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
+CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
 		   const struct nls_table *nls_codepage)
 {
 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
@@ -2512,7 +2512,7 @@
    in Samba which this routine can run into */
 
 int
-CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
+CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 	      __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
 {
 	struct smb_com_transaction2_spi_req *pSMB = NULL;
@@ -2692,8 +2692,9 @@
 }
 
 int
-CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
-		FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
+CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+		const FILE_BASIC_INFO * data, 
+		const struct nls_table *nls_codepage)
 {
 	TRANSACTION2_SPI_REQ *pSMB = NULL;
 	TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -2770,6 +2771,89 @@
 	return rc;
 }
 
+
+int
+CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+		FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_SPI_REQ *pSMB = NULL;
+	TRANSACTION2_SPI_RSP *pSMBr = NULL;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+	char *data_offset;
+
+	cFYI(1, ("In SetTimesLegacy"));
+
+SetTimesRetryLegacy:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, 530);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
+	in parent function, from the better and ususal FILE_BASIC_INFO */
+	pSMB->ParameterCount = 6 + name_len;
+	pSMB->DataCount = sizeof (FILE_INFO_STANDARD);
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+
+	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	/* I doubt that passthrough levels apply to this old
+	preNT info level */
+/*	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+	else*/
+		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
+	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
+	}
+
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SetTimesRetryLegacy;
+
+	return rc;
+}
+
 int
 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
 		    char *fileName, __u64 mode, __u64 uid, __u64 gid,
@@ -2915,10 +2999,10 @@
 	return rc;	
 }
 #ifdef CONFIG_CIFS_XATTR
-int
+ssize_t
 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
 		 const unsigned char *searchName,
-		 char * EAData, size_t size,
+		 char * EAData, size_t buf_size,
 		 const struct nls_table *nls_codepage)
 {
 		/* BB assumes one setup word */
@@ -2927,6 +3011,8 @@
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	struct fea * temp_fea;
+	char * temp_ptr;
 
 	cFYI(1, ("In Query All EAs path %s", searchName));
 QAllEAsRetry:
@@ -2942,7 +3028,7 @@
 				  , nls_codepage);
 		name_len++;	/* trailing null */
 		name_len *= 2;
-	} else {		/* BB improve the check for buffer overruns BB */
+	} else {	/* BB improve the check for buffer overruns BB */
 		name_len = strnlen(searchName, 530);
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, searchName, name_len);
@@ -3001,7 +3087,53 @@
 			ea_response_data = (struct fealist *)
 				(((char *) &pSMBr->hdr.Protocol) +
 				pSMBr->DataOffset);
+			ea_response_data->list_len = 
+				cpu_to_le32(ea_response_data->list_len);
 			cFYI(1,("ea length %d",ea_response_data->list_len));
+			name_len = ea_response_data->list_len;
+			if(name_len <= 8) {
+			/* returned EA size zeroed at top of function */
+				cFYI(1,("empty EA list returned from server"));
+			} else {
+				/* account for ea list len */
+				name_len -= 4;
+				temp_fea = ea_response_data->list;
+				temp_ptr = (char *)temp_fea;
+				while(name_len > 0) {
+					name_len -= 4;
+					temp_ptr += 4;
+					rc += temp_fea->name_len;
+				/* account for prefix user. and trailing null */
+					rc = rc + 5 + 1; 
+					if(rc<buf_size) {
+						memcpy(EAData,"user.",5);
+						EAData+=5;
+						memcpy(EAData,temp_ptr,temp_fea->name_len);
+						EAData+=temp_fea->name_len;
+						/* null terminate name */
+						*EAData = 0;
+						EAData = EAData + 1;
+					} else if(buf_size == 0) {
+						/* skip copy - calc size only */
+					} else {
+						/* stop before overrun buffer */
+						rc = -ERANGE;
+						break;
+					}
+					name_len -= temp_fea->name_len;
+					temp_ptr += temp_fea->name_len;
+					/* account for trailing null */
+					name_len--;
+					temp_ptr++;
+					temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+					name_len -= temp_fea->value_len;
+					temp_ptr += temp_fea->value_len;
+					/* BB check that temp_ptr is still within smb BB*/
+				/* no trailing null to account for in value len */
+					/* go on to next EA */
+					temp_fea = (struct fea *)temp_ptr;
+				}
+			}
 		}
 	}
 	if (pSMB)
@@ -3011,4 +3143,254 @@
 
 	return rc;
 }
+
+ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
+		const unsigned char * searchName,const unsigned char * ea_name,
+		unsigned char * ea_value, size_t buf_size, 
+		const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	struct fea * temp_fea;
+	char * temp_ptr;
+
+	cFYI(1, ("In Query EA path %s", searchName));
+QEARetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, 530);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
+	    name_len /* includes null */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in Query EA = %d", rc));
+	} else {		/* decode response */
+		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		/* BB also check enough total bytes returned */
+		/* BB we need to improve the validity checking
+		of these trans2 responses */
+		if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+			rc = -EIO;	/* bad smb */
+	   /* else if (pFindData){
+			memcpy((char *) pFindData,
+			       (char *) &pSMBr->hdr.Protocol +
+			       pSMBr->DataOffset, kl);
+		}*/ else {
+			/* check that length of list is not more than bcc */
+			/* check that each entry does not go beyond length
+			   of list */
+			/* check that each element of each entry does not
+			   go beyond end of list */
+			struct fealist * ea_response_data;
+			rc = -ENOENT;
+			/* validate_trans2_offsets() */
+			/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+			ea_response_data = (struct fealist *)
+				(((char *) &pSMBr->hdr.Protocol) +
+				pSMBr->DataOffset);
+			ea_response_data->list_len = 
+				cpu_to_le32(ea_response_data->list_len);
+			cFYI(1,("ea length %d",ea_response_data->list_len));
+			name_len = ea_response_data->list_len;
+			if(name_len <= 8) {
+			/* returned EA size zeroed at top of function */
+				cFYI(1,("empty EA list returned from server"));
+			} else {
+				/* account for ea list len */
+				name_len -= 4;
+				temp_fea = ea_response_data->list;
+				temp_ptr = (char *)temp_fea;
+				/* loop through checking if we have a matching
+				name and then return the associated value */
+				while(name_len > 0) {
+					name_len -= 4;
+					temp_ptr += 4;
+					temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+				/* BB validate that value_len falls within SMB, 
+				even though maximum for name_len is 255 */ 
+					if(memcmp(temp_fea->name,ea_name,
+						  temp_fea->name_len) == 0) {
+						/* found a match */
+						rc = temp_fea->value_len;
+				/* account for prefix user. and trailing null */
+						if(rc<=buf_size) {
+							memcpy(ea_value,
+								temp_fea->name+temp_fea->name_len+1,
+								rc);
+							/* ea values, unlike ea names,
+							are not null terminated */
+						} else if(buf_size == 0) {
+						/* skip copy - calc size only */
+						} else {
+							/* stop before overrun buffer */
+							rc = -ERANGE;
+						}
+						break;
+					}
+					name_len -= temp_fea->name_len;
+					temp_ptr += temp_fea->name_len;
+					/* account for trailing null */
+					name_len--;
+					temp_ptr++;
+					name_len -= temp_fea->value_len;
+					temp_ptr += temp_fea->value_len;
+				/* no trailing null to account for in value len */
+					/* go on to next EA */
+					temp_fea = (struct fea *)temp_ptr;
+				}
+			} 
+		}
+	}
+	if (pSMB)
+		cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto QEARetry;
+
+	return rc;
+}
+
+int
+CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+		const char * ea_name, const void * ea_value, 
+		const __u16 ea_value_len, const struct nls_table *nls_codepage)
+{
+	struct smb_com_transaction2_spi_req *pSMB = NULL;
+	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+	struct fealist *parm_data;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+
+	cFYI(1, ("In SetEA"));
+SetEARetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, 530);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+
+	pSMB->ParameterCount = 6 + name_len;
+
+	/* done calculating parms using name_len of file name,
+	now use name_len to calculate length of ea name
+	we are going to create in the inode xattrs */
+	if(ea_name == NULL)
+		name_len = 0;
+	else
+		name_len = strnlen(ea_name,255);
+
+	pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	pSMB->InformationLevel =
+		cpu_to_le16(SMB_SET_FILE_EA);
+
+	parm_data =
+		(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
+				       pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	parm_data->list_len = (__u32)(pSMB->DataCount);
+	parm_data->list[0].EA_flags = 0;
+	/* we checked above that name len is less than 255 */
+	parm_data->list[0].name_len = (__u8)name_len;;
+	/* EA names are always ASCII */
+	strncpy(parm_data->list[0].name,ea_name,name_len);
+	parm_data->list[0].name[name_len] = 0;
+	parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
+	/* caller ensures that ea_value_len is less than 64K but
+	we need to ensure that it fits within the smb */
+
+	/*BB add length check that it would fit in negotiated SMB buffer size BB */
+	/* if(ea_value_len > buffer_size - 512 (enough for header)) */
+	memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
+
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("SetPathInfo (EA) returned %d", rc));
+	}
+
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SetEARetry;
+
+	return rc;
+}
+
 #endif
diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c
--- a/fs/cifs/connect.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/connect.c	2004-07-27 18:29:53 -07:00
@@ -64,6 +64,8 @@
 	int rw:1;
 	int retry:1;
 	int intr:1;
+	int setuids:1;
+	int noperm:1;
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int sockopt;
@@ -740,6 +742,14 @@
 			vol->retry = 1;
 		} else if (strnicmp(data, "soft", 4) == 0) {
 			vol->retry = 0;
+		} else if (strnicmp(data, "perm", 4) == 0) {
+			vol->noperm = 0;
+		} else if (strnicmp(data, "noperm", 6) == 0) {
+			vol->noperm = 1;
+		} else if (strnicmp(data, "setuids", 7) == 0) {
+			vol->setuids = 1;
+		} else if (strnicmp(data, "nosetuids", 9) == 0) {
+			vol->setuids = 0;
 		} else if (strnicmp(data, "nohard", 6) == 0) {
 			vol->retry = 0;
 		} else if (strnicmp(data, "nosoft", 6) == 0) {
@@ -1314,6 +1324,12 @@
 		cifs_sb->mnt_file_mode = volume_info.file_mode;
 		cifs_sb->mnt_dir_mode = volume_info.dir_mode;
 		cFYI(1,("file mode: 0x%x  dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+
+		if(volume_info.noperm)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+		if(volume_info.setuids)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+
 		tcon =
 		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
 			     volume_info.username);
diff -Nru a/fs/cifs/dir.c b/fs/cifs/dir.c
--- a/fs/cifs/dir.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/dir.c	2004-07-27 18:29:53 -07:00
@@ -243,11 +243,19 @@
 		then we now have to set the mode if possible */
 		if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
 			(oplock & CIFS_CREATE_ACTION))
-			CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+					(__u64)current->euid,
+					(__u64)current->egid,
+					0 /* dev */,
+					cifs_sb->local_nls);
+			} else {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
 					(__u64)-1,
 					(__u64)-1,
 					0 /* dev */,
 					cifs_sb->local_nls);
+			}
 		else {
 			/* BB implement via Windows security descriptors */
 			/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
@@ -348,9 +356,16 @@
 		rc = -ENOMEM;
 	
 	if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
-		rc = CIFSSMBUnixSetPerms(xid, pTcon,
-			full_path, mode, current->euid, current->egid,
-			device_number, cifs_sb->local_nls);
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+				mode,(__u64)current->euid,(__u64)current->egid,
+				device_number, cifs_sb->local_nls);
+		} else {
+			rc = CIFSSMBUnixSetPerms(xid, pTcon,
+				full_path, mode, (__u64)-1, (__u64)-1,
+				device_number, cifs_sb->local_nls);
+		}
+
 		if(!rc) {
 			rc = cifs_get_inode_info_unix(&newinode, full_path,
 						inode->i_sb,xid);
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/inode.c	2004-07-27 18:29:53 -07:00
@@ -480,12 +480,20 @@
 		d_instantiate(direntry, newinode);
 		if(direntry->d_inode)
 			direntry->d_inode->i_nlink = 2;
-		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)                
-			CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
-				(__u64)-1,  
-				(__u64)-1,
-				0 /* dev_t */,
-				cifs_sb->local_nls);
+		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+						(__u64)current->euid,  
+						(__u64)current->egid,
+						0 /* dev_t */,
+						cifs_sb->local_nls);
+			} else {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+						(__u64)-1,  
+						(__u64)-1,
+						0 /* dev_t */,
+						cifs_sb->local_nls);
+			}
 		else { /* BB to be implemented via Windows secrty descriptors*/
 		/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
 		}
diff -Nru a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
--- a/fs/cifs/smbencrypt.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/smbencrypt.c	2004-07-27 18:29:53 -07:00
@@ -70,8 +70,6 @@
 void NTLMSSPOWFencrypt(unsigned char passwd[8],
 		       unsigned char *ntlmchalresp, unsigned char p24[24]);
 void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
-int decode_pw_buffer(char in_buffer[516], char *new_pwrd,
-		     int new_pwrd_size, __u32 * new_pw_len);
 
 /*
    This implements the X/Open SMB password encryption
diff -Nru a/fs/cifs/xattr.c b/fs/cifs/xattr.c
--- a/fs/cifs/xattr.c	2004-07-27 18:29:53 -07:00
+++ b/fs/cifs/xattr.c	2004-07-27 18:29:53 -07:00
@@ -26,27 +26,136 @@
 #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." /* BB should check for this someday */
+/* also note could add check for security prefix XATTR_SECURITY_PREFIX */ 
+
+
 int cifs_removexattr(struct dentry * direntry, const char * name)
 {
 	int rc = -EOPNOTSUPP;
 	return rc;
 }
 
-int cifs_setxattr(struct dentry * direntry, const char * name,
-        const void * value, size_t 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;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct super_block * sb;
+	char * full_path;
+
+	if(direntry == NULL)
+		return -EIO;
+	if(direntry->d_inode == NULL)
+		return -EIO;
+	sb = direntry->d_inode->i_sb;
+	if(sb == NULL)
+		return -EIO;
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+
+	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;
+	}
+	/* 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 
+		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(ea_name == NULL) {
+		cFYI(1,("Null xattr names not supported"));
+	} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
+		cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
+		  /* BB what if no namespace prefix? */
+		  /* Should we just pass them to server, except for 
+		  system and perhaps security prefixes? */
+	} else {
+		ea_name+=5; /* skip past user. prefix */
+		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
+			(__u16)value_size, cifs_sb->local_nls);
+	}
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+#endif
 	return rc;
 }
 
-ssize_t cifs_getxattr(struct dentry * direntry, const char * name,
-         void * value, size_t 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;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct super_block * sb;
+	char * full_path;
+
+	if(direntry == NULL)
+		return -EIO;
+	if(direntry->d_inode == NULL)
+		return -EIO;
+	sb = direntry->d_inode->i_sb;
+	if(sb == NULL)
+		return -EIO;
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+
+	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;
+	}
+	/* return dos attributes as pseudo xattr */
+	/* return alt name if available as pseudo attr */
+	if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)) {
+		cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
+		/* BB what if no namespace prefix? */
+		/* Should we just pass them to server, except for system? */
+	} else {
+	/* We could add a check here
+	    if proc/fs/cifs/streamstoxattr is set then
+		search server for EAs or streams to 
+		returns as xattrs */
+		ea_name+=5; /* skip past user. */
+		rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
+				buf_size, cifs_sb->local_nls);
+	}
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+#endif
 	return rc;
 }
 
-ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
+ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
 {
 	ssize_t rc = -EOPNOTSUPP;
 #ifdef CONFIG_CIFS_XATTR
@@ -55,6 +164,7 @@
 	struct cifsTconInfo *pTcon;
 	struct super_block * sb;
 	char * full_path;
+
 	if(direntry == NULL)
 		return -EIO;
 	if(direntry->d_inode == NULL)
@@ -74,13 +184,17 @@
 		FreeXid(xid);
 		return -ENOMEM;
 	}
-	/* return dosattributes as pseudo xattr */
+	/* 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 
 		returns as xattrs */
-	rc = CIFSSMBQAllEAs(xid,pTcon,full_path,ea_data,ea_size,cifs_sb->local_nls);
+	rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
+				cifs_sb->local_nls);
+
+	if (full_path)
+		kfree(full_path);
 	FreeXid(xid);
 #endif
 	return rc;
