diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-02-05 23:10:03 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-02-05 23:10:03 +0100 |
commit | 01b6aa0f9f756639fc437af62585c4bfa77319ba (patch) | |
tree | 242890e8a6f18400f43b5c60c420191029dee8f1 /sys/src/cmd/cifs | |
parent | a2abe177e4ec99e3ca22d96fd472c68a19ffe152 (diff) |
cifs: merge with steve simons latest version. thank you very much!
Diffstat (limited to 'sys/src/cmd/cifs')
-rw-r--r-- | sys/src/cmd/cifs/README.Vista | 5 | ||||
-rw-r--r-- | sys/src/cmd/cifs/cifs.c | 116 | ||||
-rw-r--r-- | sys/src/cmd/cifs/cifs.h | 4 | ||||
-rw-r--r-- | sys/src/cmd/cifs/dfs.c | 37 | ||||
-rw-r--r-- | sys/src/cmd/cifs/fs.c | 57 | ||||
-rw-r--r-- | sys/src/cmd/cifs/main.c | 102 | ||||
-rw-r--r-- | sys/src/cmd/cifs/netbios.c | 13 | ||||
-rw-r--r-- | sys/src/cmd/cifs/pack.c | 72 | ||||
-rw-r--r-- | sys/src/cmd/cifs/trans.c | 11 | ||||
-rw-r--r-- | sys/src/cmd/cifs/trans2.c | 51 | ||||
-rw-r--r-- | sys/src/cmd/cifs/transnt.c | 6 |
11 files changed, 303 insertions, 171 deletions
diff --git a/sys/src/cmd/cifs/README.Vista b/sys/src/cmd/cifs/README.Vista index 7816e0dd8..5a898233c 100644 --- a/sys/src/cmd/cifs/README.Vista +++ b/sys/src/cmd/cifs/README.Vista @@ -9,3 +9,8 @@ is just a matter of creating a new registry entry, see: -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 diff --git a/sys/src/cmd/cifs/cifs.c b/sys/src/cmd/cifs/cifs.c index c749cd5bc..42e77dab1 100644 --- a/sys/src/cmd/cifs/cifs.c +++ b/sys/src/cmd/cifs/cifs.c @@ -39,7 +39,7 @@ cifsdial(char *host, char *called, char *sysname) 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 @@ pbytes(Pkt *p) 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 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, { 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 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, 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 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, if(s->caps & CAP_UNICODE) s->flags2 |= FL2_UNICODE; + else + s->flags2 &= ~FL2_UNICODE; free(p); return 0; @@ -329,37 +326,49 @@ CIFSsession(Session *s) 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); 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,18 +376,21 @@ CIFSsession(Session *s) 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); 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); diff --git a/sys/src/cmd/cifs/cifs.h b/sys/src/cmd/cifs/cifs.h index 8acf1b350..233bf07cc 100644 --- a/sys/src/cmd/cifs/cifs.h +++ b/sys/src/cmd/cifs/cifs.h @@ -18,6 +18,7 @@ enum { 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 @@ typedef struct { 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 *pvtime(Pkt *p, uvlong n); 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 T2setfilelength(Session *s, Share *sp, int fh, FInfo *fip); 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); diff --git a/sys/src/cmd/cifs/dfs.c b/sys/src/cmd/cifs/dfs.c index 73c9a3e01..fc324e769 100644 --- 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 @@ struct Dfscache { 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 @@ dfscacheinfo(Fmt *f) 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 @@ remap(Dfscache *cp, Refer *re) 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 @@ remap(Dfscache *cp, Refer *re) 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 @@ redir1(Session *s, char *path, Dfscache *cp, int level) { 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 @@ redir1(Session *s, char *path, Dfscache *cp, int level) 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 @@ redirect(Session *s, Share *sp, char *path) } 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 @@ redirect(Session *s, Share *sp, char *path) 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) diff --git a/sys/src/cmd/cifs/fs.c b/sys/src/cmd/cifs/fs.c index 153937143..64be2225c 100644 --- 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 @@ shareinfo(Fmt *f) fmtprint(f, "\n"); } - free(sip); return 0; } @@ -359,7 +354,7 @@ period(long sec) 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; diff --git a/sys/src/cmd/cifs/main.c b/sys/src/cmd/cifs/main.c index 720f728fc..9f9f7a6f0 100644 --- a/sys/src/cmd/cifs/main.c +++ b/sys/src/cmd/cifs/main.c @@ -18,6 +18,7 @@ struct Aux { 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 @@ int Active = IDLE_TIME; /* secs until next keepalive is sent */ 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 @@ filetableinfo(Fmt *f) Aux *ap; char *type; - if((ap = Auxroot) != nil) + if((ap = Openfiles) != nil) do{ type = "walked"; if(ap->sh != -1) @@ -82,7 +83,7 @@ filetableinfo(Fmt *f) 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 @@ V2D(Dir *d, Qid qid, char *name) } 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 @@ I2D(Dir *d, Share *sp, char *path, FInfo *fi) 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 @@ newpath(char *path, char *name) 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 @@ from_cache: 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 @@ fsattach(Req *r) 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 @@ fsclone(Fid *ofid, Fid *fid) 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 @@ again: } *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 @@ fsstat(Req *r) 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 @@ fswrite(Req *r) } while(got < len && m >= n); r->ofcall.count = got; + a->mtime = time(nil); + if(m == -1) responderrstr(r); else @@ -834,12 +863,12 @@ fsdestroyfid(Fid *f) 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 @@ fsremove(Req *r) } /* 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 @@ fsremove(Req *r) 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 @@ dmpkey(char *s, void *v, int n) 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 @@ main(int argc, char **argv) case 'k': keyp = EARGF(usage()); break; + case 'l': + local++; + break; case 'm': mtpt = EARGF(usage()); break; @@ -1213,8 +1247,12 @@ main(int argc, char **argv) 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 @@ main(int argc, char **argv) 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; @@ -1240,6 +1281,9 @@ connected: Sess->secmode &= ~SECMODE_SIGN_ENABLED; #endif + if(local) + strcpy(windom, "."); + Sess->auth = getauth(method, windom, keyp, Sess->secmode, Sess->chal, Sess->challen); diff --git a/sys/src/cmd/cifs/netbios.c b/sys/src/cmd/cifs/netbios.c index eed49f29b..99dd3e32c 100644 --- a/sys/src/cmd/cifs/netbios.c +++ b/sys/src/cmd/cifs/netbios.c @@ -68,6 +68,19 @@ Gmem(uchar **p, void *v, int n) *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) { diff --git a/sys/src/cmd/cifs/pack.c b/sys/src/cmd/cifs/pack.c index 33f204413..de94f55c3 100644 --- a/sys/src/cmd/cifs/pack.c +++ b/sys/src/cmd/cifs/pack.c @@ -32,6 +32,8 @@ ppath(Pkt *p, char *str) 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 @@ pstr(Pkt *p, char *str) 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 @@ gmem(Pkt *p, void *v, int n) * 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 @@ gstr(Pkt *p, char *str, int n) 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 @@ gstr(Pkt *p, char *str, int n) n -= 2; } *(str + i) = 0; - while(*p->pos && p->pos < p->eop) gl16(p); /* @@ -270,6 +274,40 @@ gstr(Pkt *p, char *str, int n) } 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 @@ gdatetime(Pkt *p) 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 @@ gconv(Pkt *p, int conv, char *str, int n) 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; -} diff --git a/sys/src/cmd/cifs/trans.c b/sys/src/cmd/cifs/trans.c index dd2162613..7b5c6fb28 100644 --- a/sys/src/cmd/cifs/trans.c +++ b/sys/src/cmd/cifs/trans.c @@ -103,6 +103,13 @@ gtparam(Pkt *p) 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 @@ RAPsessionenum(Session *s, Share *sp, Sessinfo **sip) 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; } diff --git a/sys/src/cmd/cifs/trans2.c b/sys/src/cmd/cifs/trans2.c index 321f157ee..8ce9d1381 100644 --- a/sys/src/cmd/cifs/trans2.c +++ b/sys/src/cmd/cifs/trans2.c @@ -402,8 +402,8 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno, 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 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno, } 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 @@ T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used, 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,24 +530,26 @@ T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used, 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); 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: diff --git a/sys/src/cmd/cifs/transnt.c b/sys/src/cmd/cifs/transnt.c index cd42f8dc1..453beaa74 100644 --- a/sys/src/cmd/cifs/transnt.c +++ b/sys/src/cmd/cifs/transnt.c @@ -96,6 +96,12 @@ tntrpc(Pkt *p) } static void +gtntparam(Pkt *p) +{ + p->pos = p->tparam; +} + +static void gtntdata(Pkt *p) { p->pos = p->tdata; |