Final PATCH for 2.0.33 smbfs NT4 mtime bug [Re: Draft 2.0.34 take 2]

Ulrik Dickow (ukd@kampsax.dk)
Mon, 2 Feb 1998 22:07:40 +0100


This is a MIME encoded message.

--=_?94RVtSvwyvT5zAd5+Gk20xfRxMHhUm/s3ljV
Content-Type: text/plain; charset=iso-8859-1

On Fri, 23 Jan 1998, Johan Myreen wrote:

> Is there any chance of getting smbfs with NT4 servers fixed in 2.0.34?

Attached is a finalized version of my patch, sufficiently clean and stable
that it can be included in 2.0.34, AFAICS.

It may be used together with Bill Hawes' smbfs_inode33-patch. (He posted it
Fri Jan 23 1998 for those with "could not close" in their /var/log/messages*;
I only have two such errors after several months of heavy smbfs use. No new
errors after applying Bill's patch.)

> The 2.0.33 smbfs sqrews up file dates quite badly, giving them random
> dates. Some of my files flew back from 1998 to the 1920's.

Yes, the really bad thing is that it screws up the NT side, not just Linux'
view of things.

> A patch for this was posted on this list a while ago.
> (http://www.uwsg.indiana.edu/hypermail/linux/kernel/9801.2/0438.html)

It's easier to read and unscramble patches if you use the archive at

http://www.linuxhq.com/lnxlists/linux-kernel/

There, just save the scrambled patch as HTML and pipe it through

sed 's/&gt;/>/g; s/&lt;/</g; s/&amp;/\&/g'

o o o

My patch no longer wraps its new code into CONFIG_SMB_NT4 #ifdef's.

Instead it dynamically determines whether the server is of the NT kind (NT
3.51 & 4 and recent Sambas) or not (Win95, 3.11, ...). For NT we use the new
trans2-based code (based in part on code from Bill Hawes), for the rest we
fall back to the old core-based one. That's because:

1) For NT 4 servers we should never use the old method. Bug too serious.
2) For Win95 servers we should never use the *new* method, since they don't
seem to handle it properly (tested w/ OSR0 + Internet Exploder^H^H^Hrer)
-- and the old method works for them (at least with CONFIG_SMB_WIN95).
3) For NT 3.51 (+Samba) servers, the new method gives us the benefit of all
three time stamps, at the expense of only a small slowdown.

-- 
Ulrik Dickow, Systems Programmer           Snail Mail: Kampsax Technology
E-mail: ukd@kampsax.dk                                 P.O. Box 1142
Phone:  +45 36 39 08 00                                DK-2650 Hvidovre
Fax:    +45 36 77 03 01                                Denmark

--=_?94RVtSvwyvT5zAd5+Gk20xfRxMHhUm/s3ljV Content-Type: text/plain; name="linux-2.0.33-smbfs-ukd5.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="linux-2.0.33-smbfs-ukd5.patch"

--- linux-2.0.33/fs/smbfs/proc.c.shipped Sun Oct 26 10:55:42 1997 +++ linux-2.0.33/fs/smbfs/proc.c Sun Feb 1 20:19:13 1998 @@ -1345,6 +1345,10 @@ entry); } +/* + * This version uses the core protocol to get the attribute info. + * It works OK with Win 3.11, 95 and NT 3.51, but NOT with NT 4 (bad mtime). + */ static int smb_proc_getattr_core(struct inode *dir, const char *name, int len, struct smb_dirent *entry) @@ -1356,7 +1360,7 @@ smb_lock_server(server); - DDPRINTK("smb_proc_getattr: %s\n", name); + DDPRINTK("smb_proc_getattr_core: name=%s\n", name); retry: buf = server->packet; @@ -1378,11 +1382,99 @@ entry->f_ctime = entry->f_atime = entry->f_mtime = local2utc(DVAL(buf, smb_vwv1)); + DDPRINTK("smb_proc_getattr_core: mtime=%ld\n", entry->f_mtime); + entry->f_size = DVAL(buf, smb_vwv3); smb_unlock_server(server); return 0; } +/* + * This version uses the trans2 findfirst to get the attribute info. + * It works fine with NT 3.51 and NT 4 (any SP), but not with Win95 (ERRerror). + */ +static int +smb_proc_getattr_ff(struct inode *dir, const char *name, int len, + struct smb_dirent *entry) +{ + unsigned char *resp_data = NULL; + unsigned char *resp_param = NULL; + int resp_data_len = 0; + int resp_param_len = 0; + + char param[SMB_MAXPATHLEN + 1 + 12]; + int mask_len; + unsigned char *mask = &(param[12]); + + int result; + char *p; + struct smb_server *server = SMB_SERVER(dir); + + mask_len = smb_encode_path(server, mask, + SMB_INOP(dir), name, len) - mask; + + mask[mask_len] = 0; + + DDPRINTK("smb_proc_getattr_ff: mask=%s\n", mask); + + smb_lock_server(server); + + retry: + + WSET(param, 0, aSYSTEM | aHIDDEN | aDIR); + WSET(param, 2, 1); /* max count */ + WSET(param, 4, 2 + 1); /* close on end + close after this call */ + WSET(param, 6, 1); /* info level */ + DSET(param, 8, 0); + + result = smb_trans2_request(server, TRANSACT2_FINDFIRST, + 0, NULL, 12 + mask_len + 1, param, + &resp_data_len, &resp_data, + &resp_param_len, &resp_param); + + if (result < 0) + { + if (smb_retry(server)) + { + DPRINTK("smb_proc_getattr_ff: error=%d, retrying\n", + result); + goto retry; + } + goto out; + } + if (server->rcls != 0) + { + result = -smb_errno(server->rcls, server->err); + if (result != -ENOENT) + DPRINTK("smb_proc_getattr_ff: rcls=%d, err=%d\n", + server->rcls, server->err); + goto out; + } + /* Make sure we got enough data ... */ + result = -EINVAL; /* WVAL(resp_param, 2) is ff_searchcount */ + if (resp_data_len < 22 || WVAL(resp_param, 2) != 1) + { + DPRINTK("smb_proc_getattr_ff: bad result, len=%d, count=%d\n", + resp_data_len, WVAL(resp_param, 2)); + goto out; + } + /* Decode the response (info level 1, as in smb_decode_long_dirent) */ + p = resp_data; + entry->f_ctime = date_dos2unix(WVAL(p, 2), WVAL(p, 0)); + entry->f_atime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); + entry->f_mtime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); + entry->f_size = DVAL(p, 12); + entry->attr = WVAL(p, 20); + + DDPRINTK("smb_proc_getattr_ff: attr=%x\n", entry->attr); + + result = 0; + +out: + smb_unlock_server(server); + return result; +} + int smb_proc_getattr(struct inode *dir, const char *name, int len, struct smb_dirent *entry) @@ -1391,7 +1483,17 @@ int result; smb_init_dirent(server, entry); - result = smb_proc_getattr_core(dir, name, len, entry); + + /* Use trans2 for NT, use core protocol for others (Win95/3.11/...). + * We distinguish NT from Win95 by looking at the capabilities, + * in the same way as in Samba 1.9.18p2's reply.c. + */ + if ((server->protocol >= PROTOCOL_LANMAN2) + && (server->blkmode & (CAP_NT_SMBS | CAP_STATUS32))) + result = smb_proc_getattr_ff(dir, name, len, entry); + else + result = smb_proc_getattr_core(dir, name, len, entry); + smb_finish_dirent(server, entry); entry->len = len; @@ -1612,12 +1714,12 @@ word passlen = strlen(server->m.password); word userlen = strlen(server->m.username); +#ifdef DEBUG_SMB_PASSWD DPRINTK("smb_proc_connect: password = %s\n", server->m.password); +#endif DPRINTK("smb_proc_connect: usernam = %s\n", server->m.username); - DPRINTK("smb_proc_connect: blkmode = %d\n", - WVAL(server->packet, smb_vwv5)); if (server->protocol >= PROTOCOL_NT1) { @@ -1634,6 +1736,8 @@ server->blkmode = WVAL(server->packet, smb_vwv5); server->sesskey = DVAL(server->packet, smb_vwv6); } + DPRINTK("smb_proc_connect: blkmode (capabilities) = %x\n", + server->blkmode); if (server->max_xmit < given_max_xmit) { --- linux-2.0.33/include/linux/smbno.h.shipped Fri Apr 12 08:49:47 1996 +++ linux-2.0.33/include/linux/smbno.h Sun Feb 1 16:57:37 1998 @@ -266,4 +266,19 @@ #define TRANSACT2_FINDNOTIFYNEXT 12 #define TRANSACT2_MKDIR 13 + +/* Capabilities. See ftp://ftp.microsoft.com/developr/drg/cifs/cifs6.txt */ +#define CAP_RAW_MODE 0x0001 +#define CAP_MPX_MODE 0x0002 +#define CAP_UNICODE 0x0004 +#define CAP_LARGE_FILES 0x0008 +#define CAP_NT_SMBS 0x0010 +#define CAP_RPC_REMOTE_APIS 0x0020 +#define CAP_STATUS32 0x0040 +#define CAP_LEVEL_II_OPLOCKS 0x0080 +#define CAP_LOCK_AND_READ 0x0100 +#define CAP_NT_FIND 0x0200 +#define CAP_DFS 0x1000 +#define CAP_LARGE_READX 0x4000 + #endif /* _SMBNO_H_ */

--=_?94RVtSvwyvT5zAd5+Gk20xfRxMHhUm/s3ljV--