cifs: merge with steve simons latest version. thank you very much!
This commit is contained in:
parent
a2abe177e4
commit
01b6aa0f9f
11 changed files with 303 additions and 171 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue