From 460b96960d1946914e50316ffeefe7b41dddce91 Mon Sep 17 00:00:00 2001
From: Jeff Layton <jlayton@redhat.com>
Date: Thu, 30 Apr 2009 07:17:56 -0400
Subject: cifs: change CIFSSMBUnixQuerySymLink to use new helpers

Change CIFSSMBUnixQuerySymLink to use the new unicode helper functions.
Also change the calling conventions so that the allocation of the target
name buffer is done in CIFSSMBUnixQuerySymLink rather than by the caller.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Steve French <sfrench@us.ibm.com>
---
 fs/cifs/link.c | 22 +++++-----------------
 1 file changed, 5 insertions(+), 17 deletions(-)

(limited to 'fs/cifs/link.c')

diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 63f644000ce..e17a092f43e 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -119,16 +119,11 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 	full_path = build_path_from_dentry(direntry);
 
 	if (!full_path)
-		goto out_no_free;
+		goto out;
 
 	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
-	target_path = kmalloc(PATH_MAX, GFP_KERNEL);
-	if (!target_path) {
-		target_path = ERR_PTR(-ENOMEM);
-		goto out;
-	}
 
 	/* We could change this to:
 		if (pTcon->unix_ext)
@@ -138,8 +133,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 
 	if (pTcon->ses->capabilities & CAP_UNIX)
 		rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
-					     target_path,
-					     PATH_MAX-1,
+					     &target_path,
 					     cifs_sb->local_nls);
 	else {
 		/* BB add read reparse point symlink code here */
@@ -148,22 +142,16 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 		/* BB Add MAC style xsymlink check here if enabled */
 	}
 
-	if (rc == 0) {
-
-/* BB Add special case check for Samba DFS symlinks */
-
-		target_path[PATH_MAX-1] = 0;
-	} else {
+	if (rc != 0) {
 		kfree(target_path);
 		target_path = ERR_PTR(rc);
 	}
 
-out:
 	kfree(full_path);
-out_no_free:
+out:
 	FreeXid(xid);
 	nd_set_link(nd, target_path);
-	return NULL;	/* No cookie */
+	return NULL;
 }
 
 int
-- 
cgit v1.2.3-70-g09d2


From 9e39b0ae8af46c83b85dae7ff5251911a80fce5a Mon Sep 17 00:00:00 2001
From: Steve French <sfrench@us.ibm.com>
Date: Thu, 30 Apr 2009 21:31:15 +0000
Subject: [CIFS] Remove unneeded QuerySymlink call and fix mapping for unmapped
 status

Signed-off-by: Steve French <sfrench@us.ibm.com>
---
 fs/cifs/connect.c | 2 --
 fs/cifs/link.c    | 9 ++-------
 fs/cifs/netmisc.c | 2 ++
 fs/cifs/nterr.h   | 9 +++++++--
 fs/cifs/smberr.h  | 1 +
 5 files changed, 12 insertions(+), 11 deletions(-)

(limited to 'fs/cifs/link.c')

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 39f5362e2cb..9d2ebab53db 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3509,8 +3509,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
 					   struct nls_table *nls_info)
 {
 	int rc = 0;
-	char ntlm_session_key[CIFS_SESS_KEY_SIZE];
-	bool ntlmv2_flag = false;
 	int first_time = 0;
 	struct TCP_Server_Info *server = pSesInfo->server;
 
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index e17a092f43e..eb2fbbe865d 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -257,13 +257,8 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
 
 /* BB add read reparse point symlink code and
 	Unix extensions symlink code here BB */
-/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
-	if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
-		rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
-				tmpbuffer,
-				len - 1,
-				cifs_sb->local_nls);
-	else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
 		cERROR(1, ("SFU style symlinks not implemented yet"));
 		/* add open and read as in fs/cifs/inode.c */
 	} else {
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 8703d68f5b2..e2fe998989a 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -79,6 +79,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
 	{ErrQuota, -EDQUOT},
 	{ErrNotALink, -ENOLINK},
 	{ERRnetlogonNotStarted, -ENOPROTOOPT},
+	{ERRsymlink, -EOPNOTSUPP},
 	{ErrTooManyLinks, -EMLINK},
 	{0, 0}
 };
@@ -714,6 +715,7 @@ static const struct {
 	ERRDOS, ERRnoaccess, 0xc000028f}, {
 	ERRDOS, ERRnoaccess, 0xc0000290}, {
 	ERRDOS, ERRbadfunc, 0xc000029c}, {
+	ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
 	ERRDOS, ERRinvlevel, 0x007c0001}, };
 
 /*****************************************************************************
diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h
index 588abbb9d08..257267367d4 100644
--- a/fs/cifs/nterr.h
+++ b/fs/cifs/nterr.h
@@ -35,8 +35,6 @@ struct nt_err_code_struct {
 extern const struct nt_err_code_struct nt_errs[];
 
 /* Win32 Status codes. */
-
-#define STATUS_BUFFER_OVERFLOW            0x80000005
 #define STATUS_MORE_ENTRIES               0x0105
 #define ERROR_INVALID_PARAMETER		  0x0057
 #define ERROR_INSUFFICIENT_BUFFER	  0x007a
@@ -50,6 +48,13 @@ extern const struct nt_err_code_struct nt_errs[];
 #define STATUS_SOME_UNMAPPED       0x0107
 #define STATUS_BUFFER_OVERFLOW     0x80000005
 #define NT_STATUS_NO_MORE_ENTRIES  0x8000001a
+#define NT_STATUS_MEDIA_CHANGED    0x8000001c
+#define NT_STATUS_END_OF_MEDIA     0x8000001e
+#define NT_STATUS_MEDIA_CHECK      0x80000020
+#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
+#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
+#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
+#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
 #define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
 #define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
 #define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index 7f50e8577c1..c5084d27db7 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -110,6 +110,7 @@
 
 /* Below errors are used internally (do not come over the wire) for passthrough
    from STATUS codes to POSIX only  */
+#define ERRsymlink              0xFFFD
 #define ErrTooManyLinks         0xFFFE
 
 /* Following error codes may be generated with the ERRSRV error class.*/
-- 
cgit v1.2.3-70-g09d2


From 0e0d2cf32743c660aab20e40aeb2155c06a256db Mon Sep 17 00:00:00 2001
From: Steve French <sfrench@us.ibm.com>
Date: Fri, 1 May 2009 05:27:32 +0000
Subject: [CIFS] Remove sparse endian warnings

Removes two sparse CHECK_ENDIAN warnings from Jeffs earlier patch,
and removes the dead readlink code (after noting where in
findfirst we will need to add something like that in the future
to handle the newly discovered unexpected error on FindFirst of NTFS symlinks.

Signed-off-by: Steve French <sfrench@us.ibm.com>
---
 fs/cifs/cifssmb.c | 14 +++++----
 fs/cifs/connect.c | 23 ++++++++-------
 fs/cifs/link.c    | 87 -------------------------------------------------------
 fs/cifs/readdir.c | 37 ++++++++++++++++++++++-
 4 files changed, 58 insertions(+), 103 deletions(-)

(limited to 'fs/cifs/link.c')

diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index df5276e628b..b968e5bd7df 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2451,16 +2451,20 @@ querySymLinkRetry:
 		if (rc || (pSMBr->ByteCount < 2))
 			rc = -EIO;
 		else {
+			bool is_unicode;
 			u16 count = le16_to_cpu(pSMBr->t2.DataCount);
 
 			data_start = ((char *) &pSMBr->hdr.Protocol) +
 					   le16_to_cpu(pSMBr->t2.DataOffset);
 
+			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+				is_unicode = true;
+			else
+				is_unicode = false;
+
 			/* BB FIXME investigate remapping reserved chars here */
 			*symlinkinfo = cifs_strndup_from_ucs(data_start, count,
-						    pSMBr->hdr.Flags2 &
-							SMBFLG2_UNICODE,
-						    nls_codepage);
+						    is_unicode, nls_codepage);
 			if (!symlinkinfo)
 				rc = -ENOMEM;
 		}
@@ -3930,7 +3934,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 
 	cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
 			*num_of_nodes,
-			le16_to_cpu(pSMBr->DFSFlags)));
+			le32_to_cpu(pSMBr->DFSFlags)));
 
 	*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
 			*num_of_nodes, GFP_KERNEL);
@@ -3946,7 +3950,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 		int max_len;
 		struct dfs_info3_param *node = (*target_nodes)+i;
 
-		node->flags = le16_to_cpu(pSMBr->DFSFlags);
+		node->flags = le32_to_cpu(pSMBr->DFSFlags);
 		if (is_unicode) {
 			__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
 						GFP_KERNEL);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5bce2778163..9dcdb0c707e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2681,8 +2681,6 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
 	if (sign_CIFS_PDUs)
 		negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
-/*	if (ntlmv2_support)
-		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
 	/* setup pointers to domain name and workstation name */
 	bcc_ptr += SecurityBlobLength;
 
@@ -2780,9 +2778,10 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 				memcpy(ses->server->cryptKey,
 				       SecurityBlob2->Challenge,
 				       CIFS_CRYPTO_KEY_SIZE);
-				if (SecurityBlob2->NegotiateFlags &
+/* NTLMV2 flag is not for NTLMv2 password hash */
+/*				if (SecurityBlob2->NegotiateFlags &
 					cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
-					*pNTLMv2_flag = true;
+					*pNTLMv2_flag = true; */ /* BB wrong */
 
 				if ((SecurityBlob2->NegotiateFlags &
 					cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
@@ -3012,11 +3011,10 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	bcc_ptr += SecurityBlobLength;
 	negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
 			NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
-			0x80000000 | NTLMSSP_NEGOTIATE_128;
+			NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 |
+			NTLMSSP_NEGOTIATE_EXTENDED_SEC;
 	if (sign_CIFS_PDUs)
 		negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
-	if (ntlmv2_flag)
-		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
 
 /* setup pointers to domain name and workstation name */
 
@@ -3438,12 +3436,19 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 
 	/* above now done in SendReceive */
 	if ((rc == 0) && (tcon != NULL)) {
+		bool is_unicode;
+
 		tcon->tidStatus = CifsGood;
 		tcon->need_reconnect = false;
 		tcon->tid = smb_buffer_response->Tid;
 		bcc_ptr = pByteArea(smb_buffer_response);
 		bytes_left = BCC(smb_buffer_response);
 		length = strnlen(bcc_ptr, bytes_left - 2);
+		if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
+			is_unicode = true;
+		else
+			is_unicode = false;
+
 
 		/* skip service field (NB: this field is always ASCII) */
 		if (length == 3) {
@@ -3464,9 +3469,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 
 		/* mostly informational -- no need to fail on error here */
 		tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
-						      bytes_left,
-						      smb_buffer->Flags2 &
-							 SMBFLG2_UNICODE,
+						      bytes_left, is_unicode,
 						      nls_codepage);
 
 		cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index eb2fbbe865d..ea9d11e3dcb 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -212,93 +212,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 	return rc;
 }
 
-int
-cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
-{
-	struct inode *inode = direntry->d_inode;
-	int rc = -EACCES;
-	int xid;
-	int oplock = 0;
-	struct cifs_sb_info *cifs_sb;
-	struct cifsTconInfo *pTcon;
-	char *full_path = NULL;
-	char *tmpbuffer;
-	int len;
-	__u16 fid;
-
-	xid = GetXid();
-	cifs_sb = CIFS_SB(inode->i_sb);
-	pTcon = cifs_sb->tcon;
-
-/* BB would it be safe against deadlock to grab this sem
-      even though rename itself grabs the sem and calls lookup? */
-/*       mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
-	full_path = build_path_from_dentry(direntry);
-/*       mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
-
-	if (full_path == NULL) {
-		FreeXid(xid);
-		return -ENOMEM;
-	}
-
-	cFYI(1,
-	     ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
-	      full_path, inode, pBuffer, buflen));
-	if (buflen > PATH_MAX)
-		len = PATH_MAX;
-	else
-		len = buflen;
-	tmpbuffer = kmalloc(len, GFP_KERNEL);
-	if (tmpbuffer == NULL) {
-		kfree(full_path);
-		FreeXid(xid);
-		return -ENOMEM;
-	}
-
-/* BB add read reparse point symlink code and
-	Unix extensions symlink code here BB */
-
-	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
-		cERROR(1, ("SFU style symlinks not implemented yet"));
-		/* add open and read as in fs/cifs/inode.c */
-	} else {
-		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
-				OPEN_REPARSE_POINT, &fid, &oplock, NULL,
-				cifs_sb->local_nls,
-				cifs_sb->mnt_cifs_flags &
-					CIFS_MOUNT_MAP_SPECIAL_CHR);
-		if (!rc) {
-			rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
-				tmpbuffer,
-				len - 1,
-				fid,
-				cifs_sb->local_nls);
-			if (CIFSSMBClose(xid, pTcon, fid)) {
-				cFYI(1, ("Error closing junction point "
-					 "(open for ioctl)"));
-			}
-			/* If it is a DFS junction earlier we would have gotten
-			   PATH_NOT_COVERED returned from server so we do
-			   not need to request the DFS info here */
-		}
-	}
-	/* BB Anything else to do to handle recursive links? */
-	/* BB Should we be using page ops here? */
-
-	/* BB null terminate returned string in pBuffer? BB */
-	if (rc == 0) {
-		rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
-		cFYI(1,
-		     ("vfs_readlink called from cifs_readlink returned %d",
-		      rc));
-	}
-
-	kfree(tmpbuffer);
-	kfree(full_path);
-	FreeXid(xid);
-	return rc;
-}
-
 void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
 {
 	char *p = nd_get_link(nd);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 5bc9ab7586b..df003fe3710 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -445,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
 	}
 }
 
+/* BB eventually need to add the following helper function to
+      resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
+      we try to do FindFirst on (NTFS) directory symlinks */
+/*
+int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
+			     int xid)
+{
+	__u16 fid;
+	int len;
+	int oplock = 0;
+	int rc;
+	struct cifsTconInfo *ptcon = cifs_sb->tcon;
+	char *tmpbuffer;
+
+	rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
+			OPEN_REPARSE_POINT, &fid, &oplock, NULL,
+			cifs_sb->local_nls,
+			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	if (!rc) {
+		tmpbuffer = kmalloc(maxpath);
+		rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
+				tmpbuffer,
+				maxpath -1,
+				fid,
+				cifs_sb->local_nls);
+		if (CIFSSMBClose(xid, ptcon, fid)) {
+			cFYI(1, ("Error closing temporary reparsepoint open)"));
+		}
+	}
+}
+ */
+
 static int initiate_cifs_search(const int xid, struct file *file)
 {
 	int rc = 0;
@@ -500,7 +532,10 @@ ffirst_retry:
 			CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
 	if (rc == 0)
 		cifsFile->invalidHandle = false;
-	if ((rc == -EOPNOTSUPP) &&
+	/* BB add following call to handle readdir on new NTFS symlink errors 
+	else if STATUS_STOPPED_ON_SYMLINK
+		call get_symlink_reparse_path and retry with new path */
+	else if ((rc == -EOPNOTSUPP) &&
 		(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
 		cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
 		goto ffirst_retry;
-- 
cgit v1.2.3-70-g09d2