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
|
||||
|
||||
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->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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
/*
|
||||
|
@ -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
|
||||
gascii(Pkt *p, char *str, int n)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -417,6 +417,35 @@ T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno,
|
|||
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
|
||||
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 */
|
||||
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:
|
||||
|
|
|
@ -95,6 +95,12 @@ tntrpc(Pkt *p)
|
|||
return got;
|
||||
}
|
||||
|
||||
static void
|
||||
gtntparam(Pkt *p)
|
||||
{
|
||||
p->pos = p->tparam;
|
||||
}
|
||||
|
||||
static void
|
||||
gtntdata(Pkt *p)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue