cifs: merge with steve simons latest version. thank you very much!

This commit is contained in:
cinap_lenrek 2019-02-05 23:10:03 +01:00
parent a2abe177e4
commit 01b6aa0f9f
11 changed files with 303 additions and 171 deletions

View file

@ -9,3 +9,8 @@ is just a matter of creating a new registry entry, see:
-Steve -Steve
Tue Sep 21 17:05:48 BST 2010 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

View file

@ -39,7 +39,7 @@ cifsdial(char *host, char *called, char *sysname)
s->seq = 0; s->seq = 0;
s->seqrun = 0; s->seqrun = 0;
s->secmode = SECMODE_SIGN_ENABLED; /* hope for the best */ 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; s->macidx = -1;
@ -125,6 +125,20 @@ pbytes(Pkt *p)
p->bytebase = pl16(p, 0); /* filled in by cifsrpc() */ 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 int
cifsrpc(Pkt *p) cifsrpc(Pkt *p)
{ {
@ -233,32 +247,10 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
{ {
int d, i; int d, i;
char *ispeak = "NT LM 0.12"; char *ispeak = "NT LM 0.12";
static char *dialects[] = { static char *dialects[] = { { "NT LM 0.12" } };
// { "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" },
};
Pkt *p; 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); p = cifshdr(s, nil, SMB_COM_NEGOTIATE);
s->flags2 &= ~FL2_UNICODE;
pbytes(p); pbytes(p);
for(i = 0; i < nelem(dialects); i++){ for(i = 0; i < nelem(dialects); i++){
@ -284,25 +276,28 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
return -1; return -1;
} }
s->secmode = g8(p); /* Security mode */ s->secmode = g8(p); /* Security mode */
gl16(p); /* Max outstanding requests */ gl16(p); /* Max outstanding requests */
gl16(p); /* Max VCs */ gl16(p); /* Max VCs */
s->mtu = gl32(p); /* Max buffer size */ s->mtu = gl32(p); /* Max buffer size */
gl32(p); /* Max raw buffer size (depricated) */ gl32(p); /* Max raw buffer size (depricated) */
gl32(p); /* Session key */ gl32(p); /* Session key */
s->caps = gl32(p); /* Server capabilities */ s->caps = gl32(p); /* Server capabilities */
*svrtime = gvtime(p); /* fileserver time */ *svrtime = gvtime(p); /* fileserver time */
s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */ s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */
s->challen = g8(p); /* Encryption key length */ s->challen = g8(p); /* Encryption key length */
gl16(p); gl16(p);
gmem(p, s->chal, s->challen); /* Get the challenge */ gmem(p, s->chal, s->challen); /* Get the challenge */
gstr(p, domain, domlen); /* source domain */
{ /* 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); char *cn = emalloc9p(cnamlen);
gstr_noalign(p, cn, cnamlen); /* their name */
gstr(p, cn, cnamlen); /* their name */
if(strlen(cn) > 0) if(strlen(cn) > 0)
memcpy(cname, cn, cnamlen); memcpy(cname, cn, cnamlen);
free(cn); free(cn);
@ -310,6 +305,8 @@ CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
if(s->caps & CAP_UNICODE) if(s->caps & CAP_UNICODE)
s->flags2 |= FL2_UNICODE; s->flags2 |= FL2_UNICODE;
else
s->flags2 &= ~FL2_UNICODE;
free(p); free(p);
return 0; return 0;
@ -329,37 +326,49 @@ CIFSsession(Session *s)
s->seqrun = 1; /* activate the sequence number generation/checking */ s->seqrun = 1; /* activate the sequence number generation/checking */
p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX); p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX);
p8(p, 0xFF); /* No secondary command */ p8(p, 0xFF); /* No secondary command */
p8(p, 0); /* Reserved (must be zero) */ p8(p, 0); /* Reserved (must be zero) */
pl16(p, 0); /* Offset to next command */ pl16(p, 0); /* Offset to next command */
pl16(p, MTU); /* my max buffer size */ pl16(p, MTU); /* my max buffer size */
pl16(p, 1); /* my max multiplexed pending requests */ pl16(p, 1); /* my max multiplexed pending requests */
pl16(p, 0); /* Virtual connection # */ pl16(p, 0); /* Virtual connection # */
pl32(p, 0); /* Session key (if vc != 0) */ 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((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 */
pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */ pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */
pl32(p, 0); /* Reserved */ pl32(p, 0); /* Reserved */
pl32(p, mycaps); pl32(p, mycaps);
pbytes(p); pbytes(p);
for(q = Sess->auth->resp[0]; *q; ){ for(q = Sess->auth->resp[0]; *q; ){
q += chartorune(&r, q); q += chartorune(&r, q);
if(r > Bits16)
sysfatal("CIFSsession: '%C' utf too wide for windows\n", r);
pl16(p, toupperrune(r)); pl16(p, toupperrune(r));
} }
pl16(p, 0); pl16(p, 0);
for(q = Sess->auth->resp[0]; *q; ){ for(q = Sess->auth->resp[0]; *q; ){
q += chartorune(&r, q); q += chartorune(&r, q);
if(r > Bits16)
sysfatal("CIFSsession: '%C' utf too wide for windows\n", r);
pl16(p, r); pl16(p, r);
} }
pl16(p, 0); pl16(p, 0);
}else{ }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[0]); /* LM passwd size */
pl16(p, Sess->auth->len[1]); /* NTLM passwd size */ pl16(p, Sess->auth->len[1]); /* NTLM passwd size */
pl32(p, 0); /* Reserved */ pl32(p, 0); /* Reserved */
pl32(p, mycaps); pl32(p, mycaps);
pbytes(p); pbytes(p);
@ -367,18 +376,21 @@ CIFSsession(Session *s)
pmem(p, Sess->auth->resp[1], Sess->auth->len[1]); 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, Sess->auth->windom); /* Primary domain */
pstr(p, "plan9"); /* Client OS */ pstr(p, "plan9"); /* Client OS */
pstr(p, argv0); /* Client LAN Manager type */ pstr(p, argv0); /* Client LAN Manager type */
if(cifsrpc(p) == -1){ if(cifsrpc(p) == -1){
free(p); free(p);
return -1; return -1;
} }
g8(p); /* Reserved (0) */ g8(p); /* Reserved (0) */
gl16(p); /* Offset to next command wordcount */ gl16(p); /* Offset to next command wordcount */
Sess->isguest = gl16(p) & 1; /* logged in as guest */ Sess->isguest = gl16(p) & 1; /* logged in as guest */
gl16(p); gl16(p);

View file

@ -18,6 +18,7 @@ enum {
MAX_SHARES = 4096, /* static table of shares attached */ MAX_SHARES = 4096, /* static table of shares attached */
RAP_ERR_MOREINFO= 234, /* non-error code, more info to be fetched */ RAP_ERR_MOREINFO= 234, /* non-error code, more info to be fetched */
MAX_DFS_PATH = 512, /* MS says never more than 250 chars... */ MAX_DFS_PATH = 512, /* MS says never more than 250 chars... */
Bits16 = 0xFFFF, /* max Unicode value Windows supports */
}; };
enum { enum {
@ -451,7 +452,6 @@ typedef struct {
int type; /* o=unknown, 1=CIFS, 2=netware 3=domain */ int type; /* o=unknown, 1=CIFS, 2=netware 3=domain */
int flags; /* 1 == strip off consumed chars before resubmitting */ int flags; /* 1 == strip off consumed chars before resubmitting */
int ttl; /* time to live of this info in secs */ int ttl; /* time to live of this info in secs */
int prox; /* lower value is preferred */
char *path; /* new path */ char *path; /* new path */
char *addr; /* new server */ char *addr; /* new server */
} Refer; } Refer;
@ -584,6 +584,7 @@ extern void *pvtime(Pkt *p, uvlong n);
extern void *pdatetime(Pkt *p, long utc); extern void *pdatetime(Pkt *p, long utc);
extern void gmem(Pkt *p, void *v, int n); extern void gmem(Pkt *p, void *v, int n);
extern void gstr(Pkt *p, char *str, 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 void gascii(Pkt *p, char *str, int n);
extern uvlong gl64(Pkt *p); extern uvlong gl64(Pkt *p);
extern uvlong gb48(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 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 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 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 */ /* transnt.c */
extern int TNTquerysecurity(Session *s, Share *sp, int fh, char **usid, char **gsid); extern int TNTquerysecurity(Session *s, Share *sp, int fh, char **usid, char **gsid);

View file

@ -18,9 +18,8 @@
* this is not a problem for me and I think it hides a load * this is not a problem for me and I think it hides a load
* of problems of its own wrt plan9's private namespaces. * of problems of its own wrt plan9's private namespaces.
* *
* The proximity of my test server (AD enabled) is always 0 but some * The expiry of my test server (AD enabled) is always 0 but some
* systems may report more meaningful values. The expiry time is * systems may report more meaningful values.
* similarly zero, so I guess at 5 mins.
* *
* If the redirection points to a "hidden" share (i.e., its name * 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 * ends in a $) then the type of the redirection is 0 (unknown) even
@ -70,7 +69,6 @@ struct Dfscache {
char *path; char *path;
long expiry; /* expiry time in sec */ long expiry; /* expiry time in sec */
long rtt; /* round trip time, nsec */ long rtt; /* round trip time, nsec */
int prox; /* proximity, lower = closer */
}; };
Dfscache *Cache; Dfscache *Cache;
@ -85,8 +83,8 @@ dfscacheinfo(Fmt *f)
ex = cp->expiry - time(nil); ex = cp->expiry - time(nil);
if(ex < 0) if(ex < 0)
ex = -1; ex = -1;
fmtprint(f, "%-42s %6ld %8.1f %4d %-16s %-24s %s\n", fmtprint(f, "%-42s %6ld %8.1f %-16s %-24s %s\n",
cp->src, ex, (double)cp->rtt/1000.0L, cp->prox, cp->src, ex, (double)cp->rtt/1000.0L,
cp->host, cp->share, cp->path); cp->host, cp->share, cp->path);
} }
return 0; return 0;
@ -239,11 +237,6 @@ remap(Dfscache *cp, Refer *re)
if(*p == '\\') if(*p == '\\')
*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((n = getfields(re->addr, a, sizeof(a), 0, "/")) < 3){
if(Debug && strstr(Debug, "dfs") != nil) if(Debug && strstr(Debug, "dfs") != nil)
print(" remap nfields=%d\n", n); print(" remap nfields=%d\n", n);
@ -270,14 +263,13 @@ remap(Dfscache *cp, Refer *re)
free(cp->share); free(cp->share);
free(cp->path); free(cp->path);
cp->rtt = rtt; cp->rtt = rtt;
cp->prox = re->prox;
cp->expiry = time(nil)+re->ttl; cp->expiry = time(nil)+re->ttl;
cp->host = estrdup9p(a[Hostname]); cp->host = estrdup9p(a[Hostname]);
cp->share = estrdup9p(trimshare(a[Sharename])); cp->share = estrdup9p(trimshare(a[Sharename]));
cp->path = estrdup9p(a[Pathname]); cp->path = estrdup9p(a[Pathname]);
if(Debug && strstr(Debug, "dfs") != nil) if(Debug && strstr(Debug, "dfs") != nil)
print(" remap ping OK prox=%d host=%s share=%s path=%s\n", print(" remap ping OK host=%s share=%s path=%s\n",
cp->prox, cp->host, cp->share, cp->path); cp->host, cp->share, cp->path);
return 0; return 0;
} }
@ -286,8 +278,7 @@ redir1(Session *s, char *path, Dfscache *cp, int level)
{ {
Refer retab[16], *re; Refer retab[16], *re;
int n, gflags, used, found; int n, gflags, used, found;
if(level > 16)
if(level > 8)
return -1; return -1;
if((n = T2getdfsreferral(s, &Ipc, path, &gflags, &used, retab, if((n = T2getdfsreferral(s, &Ipc, path, &gflags, &used, retab,
@ -295,14 +286,20 @@ redir1(Session *s, char *path, Dfscache *cp, int level)
return -1; return -1;
if(! (gflags & DFS_HEADER_ROOT)) if(! (gflags & DFS_HEADER_ROOT))
used = SINT_MAX; used = 9999;
found = 0; found = 0;
for(re = retab; re < retab+n; re++){ for(re = retab; re < retab+n; re++){
if(Debug && strstr(Debug, "dfs") != nil) if(Debug && strstr(Debug, "dfs") != nil)
print("referal level=%d prox=%d path=%q addr=%q\n", print("referal level=%d path=%q addr=%q\n",
level, re->prox, re->path, re->addr); 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(gflags & DFS_HEADER_STORAGE){
if(remap(cp, re) == 0) if(remap(cp, re) == 0)
found = 1; found = 1;
@ -350,7 +347,6 @@ redirect(Session *s, Share *sp, char *path)
} else{ /* cache hit, but entry stale */ } else{ /* cache hit, but entry stale */
cp->rtt = SINT_MAX; cp->rtt = SINT_MAX;
cp->prox = SINT_MAX;
unc = smprint("//%s/%s/%s%s%s", s->auth->windom, unc = smprint("//%s/%s/%s%s%s", s->auth->windom,
cp->share, cp->path, *cp->path? "/": "", cp->share, cp->path, *cp->path? "/": "",
@ -385,7 +381,6 @@ redirect(Session *s, Share *sp, char *path)
cp = emalloc9p(sizeof(Dfscache)); cp = emalloc9p(sizeof(Dfscache));
memset(cp, 0, sizeof(Dfscache)); memset(cp, 0, sizeof(Dfscache));
cp->rtt = SINT_MAX; cp->rtt = SINT_MAX;
cp->prox = SINT_MAX;
if(redir1(s, unc, cp, 1) == -1){ if(redir1(s, unc, cp, 1) == -1){
if(Debug && strstr(Debug, "dfs") != nil) if(Debug && strstr(Debug, "dfs") != nil)

View file

@ -8,44 +8,40 @@
static char *period(long sec); 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 int
shareinfo(Fmt *f) shareinfo(Fmt *f)
{ {
int i, j, n; int type;
char *type; Share *sp;
Shareinfo2 si2; Shareinfo2 si2;
Share *sp, *sip; uvlong total, unused;
if((n = RAPshareenum(Sess, &Ipc, &sip)) < 1){ for(sp = Shares; sp < &Shares[Nshares]; sp++){
fmtprint(f, "can't enumerate shares: %r\n"); fmtprint(f, "%-24q ", sp->name);
return 0;
}
for(i = 0; i < n; i++){ if(T2fsdeviceinfo(Sess, sp, &type, nil) != -1)
fmtprint(f, "%-13q ", sip[i].name); fmtprint(f, "%-16s ", devtypes[type]);
sp = &sip[i]; if(T2fssizeinfo(Sess, sp, &total, &unused) != -1)
for(j = 0; j < Nshares; j++) fmtprint(f, "%6.1f/%-6.1f ", togb(total-unused), togb(total));
if(strcmp(Shares[j].name, sip[i].name) == 0){
sp = &Shares[j];
break;
}
if(j >= Nshares)
sp->tid = Ipc.tid;
if(RAPshareinfo(Sess, sp, sp->name, &si2) != -1){ if(RAPshareinfo(Sess, sp, sp->name, &si2) != -1){
switch(si2.type){ fmtprint(f, "%5d/%-5d %s", si2.activeusrs, si2.maxusrs, si2.comment);
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);
free(si2.name); free(si2.name);
free(si2.comment); free(si2.comment);
free(si2.path); free(si2.path);
@ -54,7 +50,6 @@ shareinfo(Fmt *f)
fmtprint(f, "\n"); fmtprint(f, "\n");
} }
free(sip);
return 0; return 0;
} }
@ -359,7 +354,7 @@ period(long sec)
min = sec / 60L; min = sec / 60L;
sec -= min * 60L; sec -= min * 60L;
if(days) 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 else
snprint(when, sizeof(when), "%d:%d:%ld ", hrs, min, sec); snprint(when, sizeof(when), "%d:%d:%ld ", hrs, min, sec);
return when; return when;

View file

@ -18,6 +18,7 @@ struct Aux {
long expire; /* expiration time of cache */ long expire; /* expiration time of cache */
long off; /* file pos of start of cache */ long off; /* file pos of start of cache */
long end; /* file pos of end of cache */ long end; /* file pos of end of cache */
long mtime; /* last modification time - windows updates it only on close */
char *cache; char *cache;
int fh; /* file handle */ int fh; /* file handle */
int sh; /* search 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 */ static int Keeppid; /* process ID of keepalive thread */
Share Shares[MAX_SHARES]; /* table of connected shares */ Share Shares[MAX_SHARES]; /* table of connected shares */
int Nshares = 0; /* number of Shares connected */ 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 */ char *Host = nil; /* host we are connected to */
static char *Ipcname = "IPC$"; static char *Ipcname = "IPC$";
@ -73,7 +74,7 @@ filetableinfo(Fmt *f)
Aux *ap; Aux *ap;
char *type; char *type;
if((ap = Auxroot) != nil) if((ap = Openfiles) != nil)
do{ do{
type = "walked"; type = "walked";
if(ap->sh != -1) if(ap->sh != -1)
@ -82,7 +83,7 @@ filetableinfo(Fmt *f)
type = "openfile"; type = "openfile";
fmtprint(f, "%-9s %s\n", type, ap->path); fmtprint(f, "%-9s %s\n", type, ap->path);
ap = ap->next; ap = ap->next;
}while(ap != Auxroot); }while(ap != Openfiles);
return 0; return 0;
} }
@ -129,7 +130,7 @@ V2D(Dir *d, Qid qid, char *name)
} }
static void static void
I2D(Dir *d, Share *sp, char *path, FInfo *fi) I2D(Dir *d, Share *sp, char *path, long mtime, FInfo *fi)
{ {
char *name; char *name;
@ -144,7 +145,10 @@ I2D(Dir *d, Share *sp, char *path, FInfo *fi)
d->gid = estrdup9p("trog"); d->gid = estrdup9p("trog");
d->muid = estrdup9p("boyd"); d->muid = estrdup9p("boyd");
d->atime = fi->accessed; 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) if(fi->attribs & ATTR_READONLY)
d->mode = 0444; d->mode = 0444;
@ -189,6 +193,27 @@ newpath(char *path, char *name)
return smprint("%s/%s", path, 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 */ /* remove "." and ".." from the cache */
static int static int
rmdots(Aux *a, int got) rmdots(Aux *a, int got)
@ -282,7 +307,7 @@ from_cache:
fi = (FInfo *)(a->cache + (off - a->off)); fi = (FInfo *)(a->cache + (off - a->off));
npath = smprint("%s/%s", mapfile(a->path), fi->name); 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) if(Billtrog == 0)
upd_names(Sess, a->sp, npath, d); upd_names(Sess, a->sp, npath, d);
free(npath); free(npath);
@ -314,13 +339,13 @@ fsattach(Req *r)
a->fh = -1; a->fh = -1;
a->sh = -1; a->sh = -1;
if(Auxroot){ if(Openfiles){
a->prev = Auxroot; a->prev = Openfiles;
a->next = Auxroot->next; a->next = Openfiles->next;
Auxroot->next->prev = a; Openfiles->next->prev = a;
Auxroot->next = a; Openfiles->next = a;
} else { } else {
Auxroot = a; Openfiles = a;
a->next = a; a->next = a;
a->prev = a; a->prev = a;
} }
@ -341,13 +366,13 @@ fsclone(Fid *ofid, Fid *fid)
a->sp = oa->sp; a->sp = oa->sp;
a->path = estrdup9p(oa->path); a->path = estrdup9p(oa->path);
if(Auxroot){ if(Openfiles){
a->prev = Auxroot; a->prev = Openfiles;
a->next = Auxroot->next; a->next = Openfiles->next;
Auxroot->next->prev = a; Openfiles->next->prev = a;
Auxroot->next = a; Openfiles->next = a;
} else { } else {
Auxroot = a; Openfiles = a;
a->next = a; a->next = a;
a->prev = a; a->prev = a;
} }
@ -483,6 +508,8 @@ again:
} }
*qid = mkqid(npath, fi.attribs & ATTR_DIRECTORY, fi.changed, 0, 0); *qid = mkqid(npath, fi.attribs & ATTR_DIRECTORY, fi.changed, 0, 0);
a->mtime = realmtime(npath);
free(a->path); free(a->path);
a->path = npath; a->path = npath;
fid->qid = *qid; fid->qid = *qid;
@ -512,7 +539,7 @@ fsstat(Req *r)
responderrstr(r); responderrstr(r);
return; return;
} }
I2D(&r->d, a->sp, a->path, &fi); I2D(&r->d, a->sp, a->path, a->mtime, &fi);
if(Billtrog == 0) if(Billtrog == 0)
upd_names(Sess, a->sp, mapfile(a->path), &r->d); upd_names(Sess, a->sp, mapfile(a->path), &r->d);
} }
@ -767,6 +794,8 @@ fswrite(Req *r)
} while(got < len && m >= n); } while(got < len && m >= n);
r->ofcall.count = got; r->ofcall.count = got;
a->mtime = time(nil);
if(m == -1) if(m == -1)
responderrstr(r); responderrstr(r);
else else
@ -834,12 +863,12 @@ fsdestroyfid(Fid *f)
if(a->cache) if(a->cache)
free(a->cache); free(a->cache);
if(a == Auxroot) if(a == Openfiles)
Auxroot = a->next; Openfiles = a->next;
a->prev->next = a->next; a->prev->next = a->next;
a->next->prev = a->prev; a->next->prev = a->prev;
if(a->next == a->prev) if(a->next == a->prev)
Auxroot = nil; Openfiles = nil;
if(a) if(a)
free(a); free(a);
} }
@ -881,7 +910,7 @@ fsremove(Req *r)
} }
/* close all instences of this file/dir */ /* close all instences of this file/dir */
if((ap = Auxroot) != nil) if((ap = Openfiles) != nil)
do{ do{
if(strcmp(ap->path, a->path) == 0){ if(strcmp(ap->path, a->path) == 0){
if(ap->sh != -1) if(ap->sh != -1)
@ -892,7 +921,7 @@ fsremove(Req *r)
ap->fh = -1; ap->fh = -1;
} }
ap = ap->next; ap = ap->next;
}while(ap != Auxroot); }while(ap != Openfiles);
try = 0; try = 0;
again: again:
if(r->fid->qid.type & QTDIR) if(r->fid->qid.type & QTDIR)
@ -1158,11 +1187,13 @@ dmpkey(char *s, void *v, int n)
void void
main(int argc, char **argv) main(int argc, char **argv)
{ {
int i, n; int i, n, local;
long svrtime; long svrtime;
char windom[64], cname[64]; 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; *cname = 0;
keyp = ""; keyp = "";
method = nil; method = nil;
@ -1190,6 +1221,9 @@ main(int argc, char **argv)
case 'k': case 'k':
keyp = EARGF(usage()); keyp = EARGF(usage());
break; break;
case 'l':
local++;
break;
case 'm': case 'm':
mtpt = EARGF(usage()); mtpt = EARGF(usage());
break; break;
@ -1213,8 +1247,12 @@ main(int argc, char **argv)
Host = argv[0]; Host = argv[0];
if(mtpt == nil && svs == nil) if(mtpt == nil && svs == nil){
mtpt = smprint("/n/%s", Host); if((p = strchr(Host, '!')) != nil)
mtpt = smprint("/n/%s", p+1);
else
mtpt = smprint("/n/%s", Host);
}
if((sysname = getenv("sysname")) == nil) if((sysname = getenv("sysname")) == nil)
sysname = "unknown"; sysname = "unknown";
@ -1227,7 +1265,10 @@ main(int argc, char **argv)
goto connected; goto connected;
strcpy(cname, Host); 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) (Sess = cifsdial(Host, "*SMBSERVER", sysname)) != nil)
goto connected; goto connected;
@ -1240,6 +1281,9 @@ connected:
Sess->secmode &= ~SECMODE_SIGN_ENABLED; Sess->secmode &= ~SECMODE_SIGN_ENABLED;
#endif #endif
if(local)
strcpy(windom, ".");
Sess->auth = getauth(method, windom, keyp, Sess->secmode, Sess->chal, Sess->auth = getauth(method, windom, keyp, Sess->secmode, Sess->chal,
Sess->challen); Sess->challen);

View file

@ -68,6 +68,19 @@ Gmem(uchar **p, void *v, int n)
*str++ = *(*p)++; *str++ = *(*p)++;
} }
static ulong
GB32(uchar **p)
{
ulong n;
n = *(*p)++ << 24;
n |= *(*p)++ << 16;
n |= *(*p)++ << 8;
n |= *(*p)++;
return n;
}
static ushort static ushort
GB16(uchar **p) GB16(uchar **p)
{ {

View file

@ -32,6 +32,8 @@ ppath(Pkt *p, char *str)
p8(p, 0); p8(p, 0);
while(*str){ while(*str){
str += chartorune(&r, str); str += chartorune(&r, str);
if(r > Bits16)
sysfatal("ppath: %C/%x utf too wide for windows\n", r, r);
if(r == L'/') if(r == L'/')
r = L'\\'; r = L'\\';
pl16(p, r); pl16(p, r);
@ -62,6 +64,8 @@ pstr(Pkt *p, char *str)
p8(p, 0); /* pad to even offset */ p8(p, 0); /* pad to even offset */
while(*str){ while(*str){
str += chartorune(&r, 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, r);
} }
pl16(p, 0); 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 * in runes or bytes, in ASCII mode this is also the size
* of the output buffer but this is not so in Unicode mode! * of the output buffer but this is not so in Unicode mode!
*/ */
void static void
gstr(Pkt *p, char *str, int n) _gstr(Pkt *p, char *str, int n, int align)
{ {
int i; int i;
Rune r; Rune r;
@ -239,9 +243,10 @@ gstr(Pkt *p, char *str, int n)
return; return;
if(p->flags2 & FL2_UNICODE){ if(p->flags2 & FL2_UNICODE){
if(((p->pos - p->buf) % 2) != 0) if(((p->pos - p->buf) % 2) != 0){
g8(p); /* strip padding to even offset */ if(align)
abort();
}
i = 0; i = 0;
while(*p->pos && n && p->pos < p->eop){ while(*p->pos && n && p->pos < p->eop){
r = gl16(p); r = gl16(p);
@ -249,7 +254,6 @@ gstr(Pkt *p, char *str, int n)
n -= 2; n -= 2;
} }
*(str + i) = 0; *(str + i) = 0;
while(*p->pos && p->pos < p->eop) while(*p->pos && p->pos < p->eop)
gl16(p); gl16(p);
/* /*
@ -269,6 +273,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 void
gascii(Pkt *p, char *str, int n) gascii(Pkt *p, char *str, int n)
{ {
@ -401,17 +439,17 @@ gdatetime(Pkt *p)
d = gl16(p); d = gl16(p);
} }
memset(&tm, 0, sizeof(tm));
tm.year = 80 + (d >> 9); tm.year = 80 + (d >> 9);
tm.mon = ((d >> 5) & 017) - 1; tm.mon = ((d >> 5) & 017) - 1;
tm.mday = d & 037; tm.mday = d & 037;
tm.zone[0] = 0;
tm.tzoff = p->s->tz;
tm.hour = t >> 11; tm.hour = t >> 11;
tm.min = (t >> 5) & 63; tm.min = (t >> 5) & 63;
tm.sec = (t & 31) << 1; tm.sec = (t & 31) << 1;
strcpy(tm.zone, "GMT");
return tm2sec(&tm) + p->s->tz; return tm2sec(&tm);
} }
long long
@ -448,19 +486,3 @@ gconv(Pkt *p, int conv, char *str, int n)
p->pos = pos; 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;
}

View file

@ -103,6 +103,13 @@ gtparam(Pkt *p)
p->pos = p->tparam; p->pos = p->tparam;
} }
static void
gtdata(Pkt *p)
{
p->pos = p->tdata;
}
int int
RAPshareenum(Session *s, Share *sp, Share **ent) RAPshareenum(Session *s, Share *sp, Share **ent)
{ {
@ -281,8 +288,8 @@ RAPsessionenum(Session *s, Share *sp, Sessinfo **sip)
ngot++; ngot++;
q++; q++;
} }
if(ngot < navail) // if(ngot < navail)
fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail); // fprint(2, "warning: %d/%d - session list incomplete\n", ngot, navail);
free(p); free(p);
return ngot; return ngot;
} }

View file

@ -402,8 +402,8 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno,
ct = gvtime(p); /* creation time */ ct = gvtime(p); /* creation time */
sn = gl32(p); /* serial number */ sn = gl32(p); /* serial number */
n = gl32(p); /* label name length */ n = gl32(p); /* label name length */
g8(p); /* reserved */ g8(p); /* reserved */
g8(p); /* reserved */ g8(p); /* reserved */
memset(label, 0, labellen); memset(label, 0, labellen);
if(n < labellen && n > 0) if(n < labellen && n > 0)
@ -417,6 +417,35 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno,
return 0; return 0;
} }
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 int
T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused) T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused)
{ {
@ -485,15 +514,15 @@ T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used,
re[i].flags = gl16(p); /* referal flags */ re[i].flags = gl16(p); /* referal flags */
switch(vers){ switch(vers){
case 1: case 1:
re[i].prox = 0; /* nearby */ re[i].ttl = 300; /* 30 mins */
re[i].ttl = 5*60; /* 5 mins */
gstr(p, tmp, sizeof tmp); gstr(p, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp); re[i].addr = estrdup9p(tmp);
re[i].path = estrdup9p(tmp); re[i].path = estrdup9p(tmp);
break; break;
case 2: case 2:
re[i].prox = gl32(p); /* not implemented in v2 */
re[i].ttl = gl32(p); re[i].ttl = gl32(p);
if(re[i].ttl == 0)
re[i].ttl = 1800;
goff(p, base, re[i].path, sizeof tmp); goff(p, base, re[i].path, sizeof tmp);
re[i].path = estrdup9p(tmp); re[i].path = estrdup9p(tmp);
goff(p, base, re[i].path, sizeof tmp);/* spurious 8.3 path */ 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); re[i].addr = estrdup9p(tmp);
break; break;
case 3: case 3:
if(re[i].flags & DFS_REFERAL_LIST){ if(re[i].flags & DFS_REFERAL_LIST){ /* normal referal */
re[i].prox = 0;
re[i].ttl = gl32(p); re[i].ttl = gl32(p);
if(re[i].ttl == 0)
re[i].ttl = 1800;
goff(p, base, tmp, sizeof tmp); goff(p, base, tmp, sizeof tmp);
re[i].path = estrdup9p(tmp); re[i].path = estrdup9p(tmp);
gl16(p); gl16(p);
goff(p, base, tmp, sizeof tmp); goff(p, base, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp); re[i].addr = estrdup9p(tmp);
} }
else{ else{ /* domain root */
re[i].prox = 0;
re[i].ttl = gl32(p); re[i].ttl = gl32(p);
if(re[i].ttl == 0)
re[i].ttl = 300;
goff(p, base, tmp, sizeof tmp); goff(p, base, tmp, sizeof tmp);
re[i].path = estrdup9p(tmp); re[i].path = estrdup9p(tmp);
gl16(p); /* spurious 8.3 path */ gl16(p); /* spurious 8.3 path */
goff(p, base, tmp, sizeof tmp); goff(p, base, tmp, sizeof tmp);
re[i].addr = estrdup9p(tmp); re[i].addr = estrdup9p(tmp);
gl16(p); /* GUID (historic) */ /* GUID (historic) here, skipped below as we know the record length */
} }
break; break;
default: default:

View file

@ -95,6 +95,12 @@ tntrpc(Pkt *p)
return got; return got;
} }
static void
gtntparam(Pkt *p)
{
p->pos = p->tparam;
}
static void static void
gtntdata(Pkt *p) gtntdata(Pkt *p)
{ {