[Samba] [PATCH] smbfs readdir fix (CFT: NetApp, OS/2)

Urban Widmark urban at teststation.com
Sat Jun 22 16:21:03 GMT 2002


On Fri, 21 Jun 2002, Vlads wrote:

> Urban,
>  I made a tcpdump files for each request.
>  Look like windows do no return the missing file in any tcp packet....

There are some differences in how the requests are made:
1. smbfs does not understand the lastname data for FIND_NEXT when in 
   infolevel 260 and does not use it in the next request. NT4/win2k does.
2. smbfs sets the continue bit to tell the server to continue from the 
   last search, NT4/win2k does not.

Even with your scripts, Vlad, I can't always trigger this error so I don't
know if I have fixed anything yet. But I have not managed to get the error
after changing the two differences above.

The attached patch is experimental. It will probably not work if you use
smbfs with unicode support.

It is meant for 2.4.19-pre9 (+- a few pre versions), or 2.4.18 with
00-smbfs-2.4.18-codepage.patch.gz [1]

Please test and let me know if it works.


smbclient does the same thing so it would be hit by this too. The fix is 
similar and if this works, perhaps you'd be interested in verifying that 
too.

Other than some extra padding bytes, I can't find anything wrong with the
smbfs requests and it looks to me like a NT4/win2k bug with the continue
bit (especially given the randomness of the error).

If someone reading this is a NetApp or OS/2 user, your feedback on this
patch would be valued. I think the change for (1) breaks at least some
NetApp versions since they (IIRC) let the lastname offset point directly
to the filename and not the record.

/Urban

[1] http://www.hojdpunkten.ac.se/054/samba/00-smbfs-2.4.18-codepage.patch.gz
-------------- next part --------------
diff -urN -X exclude linux-2.4.19-pre9-orig/fs/smbfs/proc.c linux-2.4.19-pre9-smbfs/fs/smbfs/proc.c
--- linux-2.4.19-pre9-orig/fs/smbfs/proc.c	Thu May 30 23:33:45 2002
+++ linux-2.4.19-pre9-smbfs/fs/smbfs/proc.c	Sun Jun 23 00:49:53 2002
@@ -1865,10 +1865,8 @@
  * go there for advise.
  *
  * Bugs Noted:
- * (1) When using Info Level 1 Win NT 4.0 truncates directory listings 
- * for certain patterns of names and/or lengths. The breakage pattern
- * is completely reproducible and can be toggled by the creation of a
- * single file. (E.g. echo hi >foo breaks, rm -f foo works.)
+ * (1) When using the continue bit NT4 and Windows 2000 sometimes skips a file
+ * in the FIND_NEXT reply.
  */
 static int
 smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
@@ -1952,7 +1950,7 @@
 			WSET(param, 2, max_matches);	/* max count */
 			WSET(param, 4, info_level);
 			DSET(param, 6, 0);
-			WSET(param, 10, SMB_CONTINUE_BIT|SMB_CLOSE_IF_END);
+			WSET(param, 10, SMB_CLOSE_IF_END);
 		}
 
 		result = smb_trans2_request(server, command,
@@ -2009,38 +2007,41 @@
 		 * here that those who do not point to a filename do not need
 		 * this info to continue the listing.
 		 *
-		 * OS/2 needs this and talks infolevel 1
-		 * NetApps want lastname with infolevel 260
+		 * NT4/win2k sometimes drops files without the filename.
 		 *
-		 * Both are happy if we return the data they point to. So we do.
+		 * OS/2 needs this and talks infolevel 1 (*)
+		 * NetApps want lastname with infolevel 260 (*)
+		 *
+		 * (* = probably broken by this change)
 		 */
 		mask_len = 0;
-		if (ff_lastname > 0 && ff_lastname < resp_data_len) {
-			lastname = resp_data + ff_lastname;
-
-			switch (info_level) {
-			case 260:
-				mask_len = resp_data_len - ff_lastname;
-				break;
-			case 1:
-				/* lastname points to a length byte */
-				mask_len = *lastname++;
-				if (ff_lastname + 1 + mask_len > resp_data_len)
-					mask_len = resp_data_len - ff_lastname - 1;
-				break;
-			}
-
-			/*
-			 * Update the mask string for the next message.
-			 */
-			if (mask_len < 0)
-				mask_len = 0;
+		lastname = resp_data + ff_lastname;
+		if (ff_lastname <= 0 || ff_lastname > resp_data_len) {
+			PARANOIA("lastname points beyond buffer (%d > %d)\n",
+				 ff_lastname, resp_data_len);
+		} else if (info_level == 1) {
+			/* lastname points to a length byte */
+			mask_len = *lastname++;
+			if (ff_lastname + 1 + mask_len > resp_data_len)
+				mask_len = resp_data_len - ff_lastname - 1;
 			if (mask_len > 255)
 				mask_len = 255;
 			if (mask_len)
 				strncpy(mask, lastname, mask_len);
+			mask_len = strnlen(mask, mask_len);
+		} else if (info_level == 260) {
+			/* lastname points to a dirent */
+			/* FIXME: max name length? buffer sizes? */
+			/* FIXME: NT4/win2k wants this, what about NetApp? */
+			/* FIXME: unicode patch needs to not strip the 0 */
+			mask_len = DVAL(lastname, 60);
+			p = lastname + 94;
+			if (mask_len && p[mask_len-1] == '\0')
+				mask_len--;
+
+			memcpy(mask, p, mask_len);
+			mask[mask_len] = '\0';
 		}
-		mask_len = strnlen(mask, mask_len);
 		VERBOSE("new mask, len=%d@%d of %d, mask=%.*s\n",
 			mask_len, ff_lastname, resp_data_len, mask_len, mask);
 


More information about the samba mailing list