ref: 01b6aa0f9f756639fc437af62585c4bfa77319ba
parent: a2abe177e4ec99e3ca22d96fd472c68a19ffe152
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Feb 5 18:10:03 EST 2019
cifs: merge with steve simons latest version. thank you very much!
--- a/sys/src/cmd/cifs/README.Vista
+++ b/sys/src/cmd/cifs/README.Vista
@@ -9,3 +9,8 @@
-Steve
Tue Sep 21 17:05:48 BST 2010
+
+---------------------------------
+FYI This hot-fix also works for Windows 2k8
+
+Mon Jun 25 10:38:57 BST 2012
--- a/sys/src/cmd/cifs/cifs.c
+++ b/sys/src/cmd/cifs/cifs.c
@@ -39,7 +39,7 @@
s->seq = 0;
s->seqrun = 0;
s->secmode = SECMODE_SIGN_ENABLED; /* hope for the best */
- s->flags2 = FL2_KNOWS_LONG_NAMES | FL2_HAS_LONG_NAMES | FL2_PAGEING_IO;
+ s->flags2 = FL2_KNOWS_LONG_NAMES | FL2_HAS_LONG_NAMES | FL2_PAGEING_IO | FL2_UNICODE;
s->macidx = -1;
@@ -125,6 +125,20 @@
p->bytebase = pl16(p, 0); /* filled in by cifsrpc() */
}
+static void
+dmp(int seq, uchar *buf)
+{
+ int i;
+
+ if(seq == 99)
+ print("\n ");
+ else
+ print("%+2d ", seq);
+ for(i = 0; i < 8; i++)
+ print("%02x ", buf[i] & 0xff);
+ print("\n");
+}
+
int
cifsrpc(Pkt *p)
{
@@ -233,32 +247,10 @@
{
int d, i;
char *ispeak = "NT LM 0.12";
- static char *dialects[] = {
-// { "PC NETWORK PROGRAM 1.0"},
-// { "MICROSOFT NETWORKS 1.03"},
-// { "MICROSOFT NETWORKS 3.0"},
-// { "LANMAN1.0"},
-// { "LM1.2X002"},
-// { "NT LANMAN 1.0"},
- { "NT LM 0.12" },
- };
+ static char *dialects[] = { { "NT LM 0.12" } };
Pkt *p;
- /*
- * This should not be necessary, however the XP seems to use
- * Unicode strings in its Negoiate response, but not set the
- * Flags2 UNICODE flag.
- *
- * It does however echo back the FL_UNICODE flag we set in the
- * flags2 negoiate request.
- *
- * The bodge is to force FL_UNICODE for this single request,
- * clearing it after. Later we set FL2_UNICODE if the server
- * agrees to CAP_UNICODE as it "should" be done.
- */
- s->flags2 |= FL2_UNICODE;
p = cifshdr(s, nil, SMB_COM_NEGOTIATE);
- s->flags2 &= ~FL2_UNICODE;
pbytes(p);
for(i = 0; i < nelem(dialects); i++){
@@ -284,25 +276,28 @@
return -1;
}
- s->secmode = g8(p); /* Security mode */
+ s->secmode = g8(p); /* Security mode */
- gl16(p); /* Max outstanding requests */
- gl16(p); /* Max VCs */
- s->mtu = gl32(p); /* Max buffer size */
- gl32(p); /* Max raw buffer size (depricated) */
- gl32(p); /* Session key */
- s->caps = gl32(p); /* Server capabilities */
+ gl16(p); /* Max outstanding requests */
+ gl16(p); /* Max VCs */
+ s->mtu = gl32(p); /* Max buffer size */
+ gl32(p); /* Max raw buffer size (depricated) */
+ gl32(p); /* Session key */
+ s->caps = gl32(p); /* Server capabilities */
*svrtime = gvtime(p); /* fileserver time */
- s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */
- s->challen = g8(p); /* Encryption key length */
+ s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */
+ s->challen = g8(p); /* Encryption key length */
gl16(p);
- gmem(p, s->chal, s->challen); /* Get the challenge */
- gstr(p, domain, domlen); /* source domain */
+ gmem(p, s->chal, s->challen); /* Get the challenge */
- { /* NetApp Filer seem not to report its called name */
+ /*
+ * for some weird reason the following two string always seem to be in unicode,
+ * however they are NOT byte aligned, every other packet is correctly aligned
+ */
+ gstr_noalign(p, domain, domlen); /* source domain */
+ { /* NetApp Filer seem not to report its called name */
char *cn = emalloc9p(cnamlen);
-
- gstr(p, cn, cnamlen); /* their name */
+ gstr_noalign(p, cn, cnamlen); /* their name */
if(strlen(cn) > 0)
memcpy(cname, cn, cnamlen);
free(cn);
@@ -310,6 +305,8 @@
if(s->caps & CAP_UNICODE)
s->flags2 |= FL2_UNICODE;
+ else
+ s->flags2 &= ~FL2_UNICODE;
free(p);
return 0;
@@ -329,24 +326,31 @@
s->seqrun = 1; /* activate the sequence number generation/checking */
p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX);
- p8(p, 0xFF); /* No secondary command */
- p8(p, 0); /* Reserved (must be zero) */
- pl16(p, 0); /* Offset to next command */
- pl16(p, MTU); /* my max buffer size */
- pl16(p, 1); /* my max multiplexed pending requests */
- pl16(p, 0); /* Virtual connection # */
- pl32(p, 0); /* Session key (if vc != 0) */
+ p8(p, 0xFF); /* No secondary command */
+ p8(p, 0); /* Reserved (must be zero) */
+ pl16(p, 0); /* Offset to next command */
+ pl16(p, MTU); /* my max buffer size */
+ pl16(p, 1); /* my max multiplexed pending requests */
+ pl16(p, 0); /* Virtual connection # */
+ pl32(p, 0); /* Session key (if vc != 0) */
+ if(Debug && strstr(Debug, "auth") != nil)
+ fprint(2, "mycaps=%x\n", mycaps);
if((s->secmode & SECMODE_PW_ENCRYPT) == 0) {
+ if(Debug && strstr(Debug, "auth") != nil)
+ fprint(2, "user=%d %q\npass=%d %q\n", Sess->auth->len[0], Sess->auth->resp[0], Sess->auth->len[1], Sess->auth->resp[1]);
+
pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size */
pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */
- pl32(p, 0); /* Reserved */
+ pl32(p, 0); /* Reserved */
pl32(p, mycaps);
pbytes(p);
for(q = Sess->auth->resp[0]; *q; ){
q += chartorune(&r, q);
+ if(r > Bits16)
+ sysfatal("CIFSsession: '%C' utf too wide for windows\n", r);
pl16(p, toupperrune(r));
}
pl16(p, 0);
@@ -353,13 +357,18 @@
for(q = Sess->auth->resp[0]; *q; ){
q += chartorune(&r, q);
+ if(r > Bits16)
+ sysfatal("CIFSsession: '%C' utf too wide for windows\n", r);
pl16(p, r);
}
pl16(p, 0);
}else{
+ if(Debug && strstr(Debug, "auth") != nil)
+ fprint(2, "encrypted len=%d,%d\n", Sess->auth->len[0], Sess->auth->len[1]);
+
pl16(p, Sess->auth->len[0]); /* LM passwd size */
pl16(p, Sess->auth->len[1]); /* NTLM passwd size */
- pl32(p, 0); /* Reserved */
+ pl32(p, 0); /* Reserved */
pl32(p, mycaps);
pbytes(p);
@@ -367,10 +376,13 @@
pmem(p, Sess->auth->resp[1], Sess->auth->len[1]);
}
- pstr(p, Sess->auth->user); /* Account name */
+ if(Debug && strstr(Debug, "auth") != nil)
+ fprint(2, "user=%q\nwindom=%q\nos=%s\nmanager=%s\n", Sess->auth->user, Sess->auth->windom, "plan9", argv0);
+
+ pstr(p, Sess->auth->user); /* Account name */
pstr(p, Sess->auth->windom); /* Primary domain */
- pstr(p, "plan9"); /* Client OS */
- pstr(p, argv0); /* Client LAN Manager type */
+ pstr(p, "plan9"); /* Client OS */
+ pstr(p, argv0); /* Client LAN Manager type */
if(cifsrpc(p) == -1){
free(p);
@@ -377,8 +389,8 @@
return -1;
}
- g8(p); /* Reserved (0) */
- gl16(p); /* Offset to next command wordcount */
+ g8(p); /* Reserved (0) */
+ gl16(p); /* Offset to next command wordcount */
Sess->isguest = gl16(p) & 1; /* logged in as guest */
gl16(p);
--- a/sys/src/cmd/cifs/cifs.h
+++ b/sys/src/cmd/cifs/cifs.h
@@ -18,6 +18,7 @@
MAX_SHARES = 4096, /* static table of shares attached */
RAP_ERR_MOREINFO= 234, /* non-error code, more info to be fetched */
MAX_DFS_PATH = 512, /* MS says never more than 250 chars... */
+ Bits16 = 0xFFFF, /* max Unicode value Windows supports */
};
enum {
@@ -451,7 +452,6 @@
int type; /* o=unknown, 1=CIFS, 2=netware 3=domain */
int flags; /* 1 == strip off consumed chars before resubmitting */
int ttl; /* time to live of this info in secs */
- int prox; /* lower value is preferred */
char *path; /* new path */
char *addr; /* new server */
} Refer;
@@ -584,6 +584,7 @@
extern void *pdatetime(Pkt *p, long utc);
extern void gmem(Pkt *p, void *v, int n);
extern void gstr(Pkt *p, char *str, int n);
+extern void gstr_noalign(Pkt *p, char *str, int n);
extern void gascii(Pkt *p, char *str, int n);
extern uvlong gl64(Pkt *p);
extern uvlong gb48(Pkt *p);
@@ -629,6 +630,7 @@
extern int T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno, char *label, int labellen);
extern int T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused);
extern int T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used, Refer *re, int nent);
+extern int T2fsdeviceinfo(Session *s, Share *sp, int *type, int *flags);
/* transnt.c */
extern int TNTquerysecurity(Session *s, Share *sp, int fh, char **usid, char **gsid);
--- a/sys/src/cmd/cifs/dfs.c
+++ b/sys/src/cmd/cifs/dfs.c
@@ -18,9 +18,8 @@
* this is not a problem for me and I think it hides a load
* of problems of its own wrt plan9's private namespaces.
*
- * The proximity of my test server (AD enabled) is always 0 but some
- * systems may report more meaningful values. The expiry time is
- * similarly zero, so I guess at 5 mins.
+ * The expiry of my test server (AD enabled) is always 0 but some
+ * systems may report more meaningful values.
*
* If the redirection points to a "hidden" share (i.e., its name
* ends in a $) then the type of the redirection is 0 (unknown) even
@@ -70,7 +69,6 @@
char *path;
long expiry; /* expiry time in sec */
long rtt; /* round trip time, nsec */
- int prox; /* proximity, lower = closer */
};
Dfscache *Cache;
@@ -85,8 +83,8 @@
ex = cp->expiry - time(nil);
if(ex < 0)
ex = -1;
- fmtprint(f, "%-42s %6ld %8.1f %4d %-16s %-24s %s\n",
- cp->src, ex, (double)cp->rtt/1000.0L, cp->prox,
+ fmtprint(f, "%-42s %6ld %8.1f %-16s %-24s %s\n",
+ cp->src, ex, (double)cp->rtt/1000.0L,
cp->host, cp->share, cp->path);
}
return 0;
@@ -239,11 +237,6 @@
if(*p == '\\')
*p = '/';
- if(cp->prox < re->prox){
- if(Debug && strstr(Debug, "dfs") != nil)
- print(" remap %d < %d\n", cp->prox, re->prox);
- return -1;
- }
if((n = getfields(re->addr, a, sizeof(a), 0, "/")) < 3){
if(Debug && strstr(Debug, "dfs") != nil)
print(" remap nfields=%d\n", n);
@@ -270,14 +263,13 @@
free(cp->share);
free(cp->path);
cp->rtt = rtt;
- cp->prox = re->prox;
cp->expiry = time(nil)+re->ttl;
cp->host = estrdup9p(a[Hostname]);
cp->share = estrdup9p(trimshare(a[Sharename]));
cp->path = estrdup9p(a[Pathname]);
if(Debug && strstr(Debug, "dfs") != nil)
- print(" remap ping OK prox=%d host=%s share=%s path=%s\n",
- cp->prox, cp->host, cp->share, cp->path);
+ print(" remap ping OK host=%s share=%s path=%s\n",
+ cp->host, cp->share, cp->path);
return 0;
}
@@ -286,8 +278,7 @@
{
Refer retab[16], *re;
int n, gflags, used, found;
-
- if(level > 8)
+ if(level > 16)
return -1;
if((n = T2getdfsreferral(s, &Ipc, path, &gflags, &used, retab,
@@ -295,14 +286,20 @@
return -1;
if(! (gflags & DFS_HEADER_ROOT))
- used = SINT_MAX;
+ used = 9999;
found = 0;
for(re = retab; re < retab+n; re++){
if(Debug && strstr(Debug, "dfs") != nil)
- print("referal level=%d prox=%d path=%q addr=%q\n",
- level, re->prox, re->path, re->addr);
+ print("referal level=%d path=%q addr=%q\n",
+ level, re->path, re->addr);
+ if(*re->path == 0 || *re->addr == 0){
+ free(re->addr);
+ free(re->path);
+ continue;
+ }
+
if(gflags & DFS_HEADER_STORAGE){
if(remap(cp, re) == 0)
found = 1;
@@ -350,7 +347,6 @@
} else{ /* cache hit, but entry stale */
cp->rtt = SINT_MAX;
- cp->prox = SINT_MAX;
unc = smprint("//%s/%s/%s%s%s", s->auth->windom,
cp->share, cp->path, *cp->path? "/": "",
@@ -385,7 +381,6 @@
cp = emalloc9p(sizeof(Dfscache));
memset(cp, 0, sizeof(Dfscache));
cp->rtt = SINT_MAX;
- cp->prox = SINT_MAX;
if(redir1(s, unc, cp, 1) == -1){
if(Debug && strstr(Debug, "dfs") != nil)
--- a/sys/src/cmd/cifs/fs.c
+++ b/sys/src/cmd/cifs/fs.c
@@ -8,44 +8,40 @@
static char *period(long sec);
+static char *devtypes[] = {
+ "beep", "cd", "cdfs", "datalink", "dfs", "disk", "diskfs", "fs", "inport",
+ "kbd", "mailslot", "midi-in", "midi-out", "mouse", "unc", "named-pipe", "net", "net",
+ "browser", "netfs", "null", "lpt", "nic", "lpr", "scanner", "eia-mouse",
+ "eia", "screen", "sound", "streams", "tape", "tapefs", "transport", "unknown",
+ "video", "virt-disk", "wav-in", "wav-out", "8042", "battery", "bus-exp", "modem", "vdm"
+};
+
+
+static double
+togb(uvlong n)
+{
+ return (double)n / (1024.0 * 1024.0 * 1024.0);
+}
+
int
shareinfo(Fmt *f)
{
- int i, j, n;
- char *type;
+ int type;
+ Share *sp;
Shareinfo2 si2;
- Share *sp, *sip;
+ uvlong total, unused;
- if((n = RAPshareenum(Sess, &Ipc, &sip)) < 1){
- fmtprint(f, "can't enumerate shares: %r\n");
- return 0;
- }
+ for(sp = Shares; sp < &Shares[Nshares]; sp++){
+ fmtprint(f, "%-24q ", sp->name);
- for(i = 0; i < n; i++){
- fmtprint(f, "%-13q ", sip[i].name);
+ if(T2fsdeviceinfo(Sess, sp, &type, nil) != -1)
+ fmtprint(f, "%-16s ", devtypes[type]);
- sp = &sip[i];
- for(j = 0; j < Nshares; j++)
- if(strcmp(Shares[j].name, sip[i].name) == 0){
- sp = &Shares[j];
- break;
- }
- if(j >= Nshares)
- sp->tid = Ipc.tid;
+ if(T2fssizeinfo(Sess, sp, &total, &unused) != -1)
+ fmtprint(f, "%6.1f/%-6.1f ", togb(total-unused), togb(total));
if(RAPshareinfo(Sess, sp, sp->name, &si2) != -1){
- switch(si2.type){
- case STYPE_DISKTREE: type = "disk"; break;
- case STYPE_PRINTQ: type = "printq"; break;
- case STYPE_DEVICE: type = "device"; break;
- case STYPE_IPC: type = "ipc"; break;
- case STYPE_SPECIAL: type = "special"; break;
- case STYPE_TEMP: type = "temp"; break;
- default: type = "unknown"; break;
- }
-
- fmtprint(f, "%-8s %5d/%-5d %s", type,
- si2.activeusrs, si2.maxusrs, si2.comment);
+ fmtprint(f, "%5d/%-5d %s", si2.activeusrs, si2.maxusrs, si2.comment);
free(si2.name);
free(si2.comment);
free(si2.path);
@@ -54,7 +50,6 @@
fmtprint(f, "\n");
}
- free(sip);
return 0;
}
@@ -359,7 +354,7 @@
min = sec / 60L;
sec -= min * 60L;
if(days)
- snprint(when, sizeof(when), "%d %d:%d:%ld ", days, hrs, min, sec);
+ snprint(when, sizeof(when), "%d,%d:%d:%ld ", days, hrs, min, sec);
else
snprint(when, sizeof(when), "%d:%d:%ld ", hrs, min, sec);
return when;
--- a/sys/src/cmd/cifs/main.c
+++ b/sys/src/cmd/cifs/main.c
@@ -18,6 +18,7 @@
long expire; /* expiration time of cache */
long off; /* file pos of start of cache */
long end; /* file pos of end of cache */
+ long mtime; /* last modification time - windows updates it only on close */
char *cache;
int fh; /* file handle */
int sh; /* search handle */
@@ -38,7 +39,7 @@
static int Keeppid; /* process ID of keepalive thread */
Share Shares[MAX_SHARES]; /* table of connected shares */
int Nshares = 0; /* number of Shares connected */
-Aux *Auxroot = nil; /* linked list of Aux structs */
+Aux *Openfiles = nil; /* linked list of Aux structs */
char *Host = nil; /* host we are connected to */
static char *Ipcname = "IPC$";
@@ -73,7 +74,7 @@
Aux *ap;
char *type;
- if((ap = Auxroot) != nil)
+ if((ap = Openfiles) != nil)
do{
type = "walked";
if(ap->sh != -1)
@@ -82,7 +83,7 @@
type = "openfile";
fmtprint(f, "%-9s %s\n", type, ap->path);
ap = ap->next;
- }while(ap != Auxroot);
+ }while(ap != Openfiles);
return 0;
}
@@ -129,7 +130,7 @@
}
static void
-I2D(Dir *d, Share *sp, char *path, FInfo *fi)
+I2D(Dir *d, Share *sp, char *path, long mtime, FInfo *fi)
{
char *name;
@@ -144,7 +145,10 @@
d->gid = estrdup9p("trog");
d->muid = estrdup9p("boyd");
d->atime = fi->accessed;
- d->mtime = fi->written;
+ if(mtime > fi->written)
+ d->mtime = mtime;
+ else
+ d->mtime = fi->written;
if(fi->attribs & ATTR_READONLY)
d->mode = 0444;
@@ -189,6 +193,27 @@
return smprint("%s/%s", path, name);
}
+/*
+ * get the last write time if the file is open -
+ * windows only updates mtime when the file is closed
+ * which is not good enough for acme.
+ */
+static long
+realmtime(char *path)
+{
+ Aux *a;
+
+ if((a = Openfiles) == nil)
+ return 0;
+
+ do{
+ if(a->fh != -1 && cistrcmp(path, a->path) == 0)
+ return a->mtime;
+ a = a->next;
+ }while(a != Openfiles);
+ return 0;
+}
+
/* remove "." and ".." from the cache */
static int
rmdots(Aux *a, int got)
@@ -282,7 +307,7 @@
fi = (FInfo *)(a->cache + (off - a->off));
npath = smprint("%s/%s", mapfile(a->path), fi->name);
- I2D(d, a->sp, npath, fi);
+ I2D(d, a->sp, npath, realmtime(npath), fi);
if(Billtrog == 0)
upd_names(Sess, a->sp, npath, d);
free(npath);
@@ -314,13 +339,13 @@
a->fh = -1;
a->sh = -1;
- if(Auxroot){
- a->prev = Auxroot;
- a->next = Auxroot->next;
- Auxroot->next->prev = a;
- Auxroot->next = a;
+ if(Openfiles){
+ a->prev = Openfiles;
+ a->next = Openfiles->next;
+ Openfiles->next->prev = a;
+ Openfiles->next = a;
} else {
- Auxroot = a;
+ Openfiles = a;
a->next = a;
a->prev = a;
}
@@ -341,13 +366,13 @@
a->sp = oa->sp;
a->path = estrdup9p(oa->path);
- if(Auxroot){
- a->prev = Auxroot;
- a->next = Auxroot->next;
- Auxroot->next->prev = a;
- Auxroot->next = a;
+ if(Openfiles){
+ a->prev = Openfiles;
+ a->next = Openfiles->next;
+ Openfiles->next->prev = a;
+ Openfiles->next = a;
} else {
- Auxroot = a;
+ Openfiles = a;
a->next = a;
a->prev = a;
}
@@ -483,6 +508,8 @@
}
*qid = mkqid(npath, fi.attribs & ATTR_DIRECTORY, fi.changed, 0, 0);
+ a->mtime = realmtime(npath);
+
free(a->path);
a->path = npath;
fid->qid = *qid;
@@ -512,7 +539,7 @@
responderrstr(r);
return;
}
- I2D(&r->d, a->sp, a->path, &fi);
+ I2D(&r->d, a->sp, a->path, a->mtime, &fi);
if(Billtrog == 0)
upd_names(Sess, a->sp, mapfile(a->path), &r->d);
}
@@ -767,6 +794,8 @@
} while(got < len && m >= n);
r->ofcall.count = got;
+ a->mtime = time(nil);
+
if(m == -1)
responderrstr(r);
else
@@ -834,12 +863,12 @@
if(a->cache)
free(a->cache);
- if(a == Auxroot)
- Auxroot = a->next;
+ if(a == Openfiles)
+ Openfiles = a->next;
a->prev->next = a->next;
a->next->prev = a->prev;
if(a->next == a->prev)
- Auxroot = nil;
+ Openfiles = nil;
if(a)
free(a);
}
@@ -881,7 +910,7 @@
}
/* close all instences of this file/dir */
- if((ap = Auxroot) != nil)
+ if((ap = Openfiles) != nil)
do{
if(strcmp(ap->path, a->path) == 0){
if(ap->sh != -1)
@@ -892,7 +921,7 @@
ap->fh = -1;
}
ap = ap->next;
- }while(ap != Auxroot);
+ }while(ap != Openfiles);
try = 0;
again:
if(r->fid->qid.type & QTDIR)
@@ -1158,11 +1187,13 @@
void
main(int argc, char **argv)
{
- int i, n;
+ int i, n, local;
long svrtime;
char windom[64], cname[64];
- char *method, *sysname, *keyp, *mtpt, *svs;
+ char *p, *method, *sysname, *keyp, *mtpt, *svs;
+ static char *sh[1024];
+ local = 0;
*cname = 0;
keyp = "";
method = nil;
@@ -1190,6 +1221,9 @@
case 'k':
keyp = EARGF(usage());
break;
+ case 'l':
+ local++;
+ break;
case 'm':
mtpt = EARGF(usage());
break;
@@ -1213,8 +1247,12 @@
Host = argv[0];
- if(mtpt == nil && svs == nil)
- mtpt = smprint("/n/%s", Host);
+ if(mtpt == nil && svs == nil){
+ if((p = strchr(Host, '!')) != nil)
+ mtpt = smprint("/n/%s", p+1);
+ else
+ mtpt = smprint("/n/%s", Host);
+ }
if((sysname = getenv("sysname")) == nil)
sysname = "unknown";
@@ -1227,7 +1265,10 @@
goto connected;
strcpy(cname, Host);
- if((Sess = cifsdial(Host, Host, sysname)) != nil ||
+ if((p = strchr(cname, '!')) != nil)
+ strcpy(cname, p+1);
+
+ if((Sess = cifsdial(Host, cname, sysname)) != nil ||
(Sess = cifsdial(Host, "*SMBSERVER", sysname)) != nil)
goto connected;
@@ -1239,6 +1280,9 @@
#ifndef DEBUG_MAC
Sess->secmode &= ~SECMODE_SIGN_ENABLED;
#endif
+
+ if(local)
+ strcpy(windom, ".");
Sess->auth = getauth(method, windom, keyp, Sess->secmode, Sess->chal,
Sess->challen);
--- a/sys/src/cmd/cifs/netbios.c
+++ b/sys/src/cmd/cifs/netbios.c
@@ -68,6 +68,19 @@
*str++ = *(*p)++;
}
+
+static ulong
+GB32(uchar **p)
+{
+ ulong n;
+
+ n = *(*p)++ << 24;
+ n |= *(*p)++ << 16;
+ n |= *(*p)++ << 8;
+ n |= *(*p)++;
+ return n;
+}
+
static ushort
GB16(uchar **p)
{
--- a/sys/src/cmd/cifs/pack.c
+++ b/sys/src/cmd/cifs/pack.c
@@ -32,6 +32,8 @@
p8(p, 0);
while(*str){
str += chartorune(&r, str);
+ if(r > Bits16)
+ sysfatal("ppath: %C/%x utf too wide for windows\n", r, r);
if(r == L'/')
r = L'\\';
pl16(p, r);
@@ -62,6 +64,8 @@
p8(p, 0); /* pad to even offset */
while(*str){
str += chartorune(&r, str);
+ if(r > Bits16)
+ sysfatal("pstr: %C/%x utf too wide for windows\n", r, r);
pl16(p, r);
}
pl16(p, 0);
@@ -229,8 +233,8 @@
* in runes or bytes, in ASCII mode this is also the size
* of the output buffer but this is not so in Unicode mode!
*/
-void
-gstr(Pkt *p, char *str, int n)
+static void
+_gstr(Pkt *p, char *str, int n, int align)
{
int i;
Rune r;
@@ -239,9 +243,10 @@
return;
if(p->flags2 & FL2_UNICODE){
- if(((p->pos - p->buf) % 2) != 0)
- g8(p); /* strip padding to even offset */
-
+ if(((p->pos - p->buf) % 2) != 0){
+ if(align)
+ abort();
+ }
i = 0;
while(*p->pos && n && p->pos < p->eop){
r = gl16(p);
@@ -249,7 +254,6 @@
n -= 2;
}
*(str + i) = 0;
-
while(*p->pos && p->pos < p->eop)
gl16(p);
/*
@@ -270,6 +274,40 @@
}
void
+gstr(Pkt *p, char *str, int n)
+{
+ _gstr(p, str, n, 1);
+}
+
+void
+gstr_noalign(Pkt *p, char *str, int n)
+{
+ _gstr(p, str, n, 0);
+}
+
+/*
+ * Because DFS uses a string heap rather than strings embedded in the
+ * data packet, experience (rather than any spec) tells, us we must
+ * turn off the 16bit alignment for unicode strings.
+ */
+void
+goff(Pkt *p, uchar *base, char *str, int n)
+{
+ int off;
+ uchar *pos;
+
+ off = gl16(p);
+ if(off == 0 || base + off > p->eop){
+ memset(str, 0, n);
+ return;
+ }
+ pos = p->pos;
+ p->pos = base + off;
+ gstr_noalign(p, str, n);
+ p->pos = pos;
+}
+
+void
gascii(Pkt *p, char *str, int n)
{
if(!n || !str)
@@ -401,17 +439,17 @@
d = gl16(p);
}
- memset(&tm, 0, sizeof(tm));
tm.year = 80 + (d >> 9);
tm.mon = ((d >> 5) & 017) - 1;
tm.mday = d & 037;
+ tm.zone[0] = 0;
+ tm.tzoff = p->s->tz;
tm.hour = t >> 11;
tm.min = (t >> 5) & 63;
tm.sec = (t & 31) << 1;
- strcpy(tm.zone, "GMT");
- return tm2sec(&tm) + p->s->tz;
+ return tm2sec(&tm);
}
long
@@ -448,19 +486,3 @@
p->pos = pos;
}
-void
-goff(Pkt *p, uchar *base, char *str, int n)
-{
- int off;
- uchar *pos;
-
- off = gl16(p);
- if(off == 0 || base + off > p->eop){
- memset(str, 0, n);
- return;
- }
- pos = p->pos;
- p->pos = base + off;
- gstr(p, str, n);
- p->pos = pos;
-}
--- a/sys/src/cmd/cifs/trans.c
+++ b/sys/src/cmd/cifs/trans.c
@@ -103,6 +103,13 @@
p->pos = p->tparam;
}
+static void
+gtdata(Pkt *p)
+{
+ p->pos = p->tdata;
+}
+
+
int
RAPshareenum(Session *s, Share *sp, Share **ent)
{
@@ -281,8 +288,8 @@
ngot++;
q++;
}
- if(ngot < navail)
- fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
+// if(ngot < navail)
+// fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
free(p);
return ngot;
}
--- a/sys/src/cmd/cifs/trans2.c
+++ b/sys/src/cmd/cifs/trans2.c
@@ -402,8 +402,8 @@
ct = gvtime(p); /* creation time */
sn = gl32(p); /* serial number */
n = gl32(p); /* label name length */
- g8(p); /* reserved */
- g8(p); /* reserved */
+ g8(p); /* reserved */
+ g8(p); /* reserved */
memset(label, 0, labellen);
if(n < labellen && n > 0)
@@ -418,6 +418,35 @@
}
int
+T2fsdeviceinfo(Session *s, Share *sp, int *type, int *flags)
+{
+ Pkt *p;
+ long t, f;
+
+ p = t2hdr(s, sp, TRANS2_QUERY_FS_INFORMATION);
+ pt2param(p);
+ pl16(p, SMB_QUERY_FS_DEVICE_INFO); /* Information level */
+
+ pt2data(p);
+
+ if(t2rpc(p) == -1){
+ free(p);
+ return -1;
+ }
+
+ gt2data(p);
+ t = gl32(p); /* device type */
+ f = gl32(p); /* device characteristics */
+
+ if(type)
+ *type = t;
+ if(flags)
+ *flags = f;
+ free(p);
+ return 0;
+}
+
+int
T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused)
{
Pkt *p;
@@ -485,15 +514,15 @@
re[i].flags = gl16(p); /* referal flags */
switch(vers){
case 1:
- re[i].prox = 0; /* nearby */
- re[i].ttl = 5*60; /* 5 mins */
+ re[i].ttl = 300; /* 30 mins */
gstr(p, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp);
re[i].path = estrdup9p(tmp);
break;
case 2:
- re[i].prox = gl32(p); /* not implemented in v2 */
re[i].ttl = gl32(p);
+ if(re[i].ttl == 0)
+ re[i].ttl = 1800;
goff(p, base, re[i].path, sizeof tmp);
re[i].path = estrdup9p(tmp);
goff(p, base, re[i].path, sizeof tmp);/* spurious 8.3 path */
@@ -501,9 +530,10 @@
re[i].addr = estrdup9p(tmp);
break;
case 3:
- if(re[i].flags & DFS_REFERAL_LIST){
- re[i].prox = 0;
+ if(re[i].flags & DFS_REFERAL_LIST){ /* normal referal */
re[i].ttl = gl32(p);
+ if(re[i].ttl == 0)
+ re[i].ttl = 1800;
goff(p, base, tmp, sizeof tmp);
re[i].path = estrdup9p(tmp);
gl16(p);
@@ -510,15 +540,16 @@
goff(p, base, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp);
}
- else{
- re[i].prox = 0;
+ else{ /* domain root */
re[i].ttl = gl32(p);
+ if(re[i].ttl == 0)
+ re[i].ttl = 300;
goff(p, base, tmp, sizeof tmp);
re[i].path = estrdup9p(tmp);
gl16(p); /* spurious 8.3 path */
goff(p, base, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp);
- gl16(p); /* GUID (historic) */
+ /* GUID (historic) here, skipped below as we know the record length */
}
break;
default:
--- a/sys/src/cmd/cifs/transnt.c
+++ b/sys/src/cmd/cifs/transnt.c
@@ -96,6 +96,12 @@
}
static void
+gtntparam(Pkt *p)
+{
+ p->pos = p->tparam;
+}
+
+static void
gtntdata(Pkt *p)
{
p->pos = p->tdata;