static Req* getreq(Srv *s) { int32_t n; uint8_t *buf; Fcall f; Req *r; qlock(&s->rlock); if((n = read9pmsg(s->infd, s->rbuf, s->msize)) <= 0){ qunlock(&s->rlock); return nil; } buf = emalloc9p(n); memmove(buf, s->rbuf, n); qunlock(&s->rlock); if(convM2S(buf, n, &f) != n){ free(buf); return nil; } if((r=allocreq(s->rpool, f.tag)) == nil){ /* duplicate tag: cons up a fake Req */ r = emalloc9p(sizeof *r); incref(&r->ref); r->tag = f.tag; r->ifcall = f; r->error = Eduptag; r->buf = buf; r->responded = 0; r->type = 0; r->srv = s; r->pool = nil; if(chatty9p) fprint(2, "<-%d- %F: dup tag\n", s->infd, &f); return r; } r->srv = s; r->responded = 0; r->buf = buf; r->ifcall = f; memset(&r->ofcall, 0, sizeof r->ofcall); r->type = r->ifcall.type; if(chatty9p) if(r->error) fprint(2, "<-%d- %F: %s\n", s->infd, &r->ifcall, r->error); else fprint(2, "<-%d- %F\n", s->infd, &r->ifcall); return r; }
static void changemsize(Srv *srv, int msize) { if(srv->rbuf && srv->wbuf && srv->msize == msize) return; qlock(&srv->rlock); qlock(&srv->wlock); srv->msize = msize; free(srv->rbuf); free(srv->wbuf); srv->rbuf = emalloc9p(msize); srv->wbuf = emalloc9p(msize); qunlock(&srv->rlock); qunlock(&srv->wlock); }
static Auth * auth_plain(char *windom, char *keyp, uchar *chal, int len) { UserPasswd *up; static Auth *ap; USED(chal, len); up = auth_getuserpasswd(auth_getkey, "windom=%s proto=pass service=cifs %s", windom, keyp); if(! up) sysfatal("cannot get key - %r"); ap = emalloc9p(sizeof(Auth)); memset(ap, 0, sizeof(ap)); ap->user = estrdup9p(up->user); ap->windom = estrdup9p(windom); ap->resp[0] = estrdup9p(up->passwd); ap->len[0] = strlen(up->passwd); memset(up->passwd, 0, strlen(up->passwd)); free(up); return ap; }
static File* allocfile(void) { int i, a; File *f; enum { N = 16 }; qlock(&filelk); if(freefilelist == nil){ f = emalloc9p(N*sizeof(*f)); for(i=0; i<N-1; i++) f[i].aux = &f[i+1]; f[N-1].aux = nil; f[0].allocd = 1; freefilelist = f; } f = freefilelist; freefilelist = f->aux; qunlock(&filelk); a = f->allocd; memset(f, 0, sizeof *f); f->allocd = a; return f; }
static void rstat(Req *r, char *error) { int n; uchar *statbuf; uchar tmp[BIT16SZ]; if(error) return; if(convD2M(&r->d, tmp, BIT16SZ) != BIT16SZ){ r->error = "convD2M(_,_,BIT16SZ) did not return BIT16SZ"; return; } n = GBIT16(tmp)+BIT16SZ; statbuf = emalloc9p(n); if(statbuf == nil){ r->error = "out of memory"; return; } r->ofcall.nstat = convD2M(&r->d, statbuf, n); r->ofcall.stat = statbuf; /* freed in closereq */ if(r->ofcall.nstat <= BIT16SZ){ r->error = "convD2M fails"; free(statbuf); return; } }
/* * parse a command written to a device */ Cmdbuf* parsecmd(char *p, int n) { Cmdbuf *cb; int nf; char *sp; nf = ncmdfield(p, n); /* allocate Cmdbuf plus string pointers plus copy of string including \0 */ sp = emalloc9p(sizeof(*cb) + nf * sizeof(char*) + n + 1); cb = (Cmdbuf*)sp; cb->f = (char**)(&cb[1]); cb->buf = (char*)(&cb->f[nf]); memmove(cb->buf, p, n); /* dump new line and null terminate */ if(n > 0 && cb->buf[n-1] == '\n') n--; cb->buf[n] = '\0'; cb->nf = tokenize(cb->buf, cb->f, nf-1); cb->f[cb->nf] = nil; return cb; }
static void fscreate(Req *r) { FInfo fi; int rc, is_dir; char *npath; Aux *a = r->fid->aux; a->end = a->off = 0; a->cache = emalloc9p(max(Sess->mtu, MTU)); is_dir = (r->ifcall.perm & DMDIR) == DMDIR; npath = smprint("%s/%s", a->path, r->ifcall.name); if(Sess->caps & CAP_NT_SMBS) rc = ntcreateopen(a, mapfile(npath), r->ifcall.mode, r->ifcall.perm, 1, is_dir, &fi); else rc = smbcreateopen(a, mapfile(npath), r->ifcall.mode, r->ifcall.perm, 1, is_dir, &fi); if(rc == -1){ free(npath); responderrstr(r); return; } r->fid->qid = mkqid(npath, fi.attribs & ATTR_DIRECTORY, fi.changed, 0, 0); r->ofcall.qid = r->fid->qid; free(a->path); a->path = npath; respond(r, nil); }
static char* fsclone(Fid *ofid, Fid *fid) { Aux *oa = ofid->aux; Aux *a = emalloc9p(sizeof(Aux)); fid->aux = a; memset(a, 0, sizeof(Aux)); a->sh = -1; a->fh = -1; 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; } else { Auxroot = a; a->next = a; a->prev = a; } return nil; }
static void fsopen(Req *r) { int rc; FInfo fi; Aux *a = r->fid->aux; a->end = a->off = 0; a->cache = emalloc9p(max(Sess->mtu, MTU)); if(ptype(r->fid->qid.path) == Pinfo){ if(makeinfo(pindex(r->fid->qid.path)) != -1) respond(r, nil); else respond(r, "cannot generate info"); return; } if(r->fid->qid.type & QTDIR){ respond(r, nil); return; } if(Sess->caps & CAP_NT_SMBS) rc = ntcreateopen(a, mapfile(a->path), r->ifcall.mode, 0777, 0, 0, &fi); else rc = smbcreateopen(a, mapfile(a->path), r->ifcall.mode, 0777, 0, 0, &fi); if(rc == -1){ responderrstr(r); return; } respond(r, nil); }
static void fscreate(Req* r) { File* file; Query* q; char* name; char* uid; int mode; File* f; file = r->fid->file; name = r->ifcall.name; uid = r->fid->uid; mode = r->fid->file->dir.mode & 0x777 & r->ifcall.perm; mode |= (r->ifcall.perm & ~0x777); if(mode&DMDIR){ respond(r, "queries cannot be directories"); return; } if(f = createfile(file, name, uid, mode, nil)){ q = emalloc9p(sizeof *q); q->text = estrdup9p(""); q->expr = nil; f->aux = q; closefile(r->fid->file); r->fid->file = f; r->ofcall.qid = f->dir.qid; respond(r, nil); } else respond(r, "problem creating file"); }
static void fsattach(Req *r) { Revfile *rf; if(r->ifcall.aname && r->ifcall.aname[0]){ respond(r, "invalid attach specifier"); return; } r->fid->qid.path = Qroot; r->fid->qid.type = QTDIR; r->fid->qid.vers = 0; r->ofcall.qid = r->fid->qid; rf = emalloc9p(sizeof(*rf)); rf->level = Qroot; rf->info = nil; rf->tree = nil; rf->node = nil; rf->rlog = nil; rf->fd = -1; rf->doff = 0; rf->buf = nil; r->fid->aux = rf; respond(r, nil); }
static CipherState* initblowfish(Conn *c, int dir) { int i; CipherState *cs; if (debug > 1) { fprint(2, "initblowfish dir:%d\ns2cek: ", dir); for(i = 0; i < 16; ++i) fprint(2, "%02x", c->s2cek[i]); fprint(2, "\nc2sek: "); for(i = 0; i < 16; ++i) fprint(2, "%02x", c->c2sek[i]); fprint(2, "\ns2civ: "); for(i = 0; i < 8; ++i) fprint(2, "%02x", c->s2civ[i]); fprint(2, "\nc2siv: "); for(i = 0; i < 8; ++i) fprint(2, "%02x", c->c2siv[i]); fprint(2, "\n"); } cs = emalloc9p(sizeof(CipherState)); memset(cs, '\0', sizeof *cs); fprint(2, "cs: %p\n", cs); if(dir) setupBFstate(&cs->state, c->s2cek, 16, c->s2civ); else setupBFstate(&cs->state, c->c2sek, 16, c->c2siv); return cs; }
uchar* getrange(Block *b) { uchar *data; char *status; int netfd; static Biobuf netbio; b->len = Blocksize; if(b->off + b->len > size) b->len = size - b->off; if(debug) print("getrange: %lld %lld\n", b->off, b->len); netfd = dialhttp(&netbio); fprint(netfd, "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "Accept-Encoding:\r\n" "Range: bytes=%lld-%lld\r\n" "\r\n", get, host, b->off, b->off+b->len); Bflush(&netbio); status = readhttphdr(&netbio, nil); if(status == nil) return nil; /* * Some servers (e.g., www.google.com) return 200 OK * when you ask for the entire page in one range. */ if(strstr(status, "206 Partial Content")==nil && (b->off!=0 || b->len!=size || strstr(status, "200 OK")==nil)){ free(status); close(netfd); werrstr("did not get requested range"); return nil; } free(status); data = emalloc9p(b->len); if(Bread(&netbio, data, b->len) != b->len){ free(data); close(netfd); werrstr("not enough bytes read"); return nil; } b->p = data; close(netfd); return data; }
Reqpool* allocreqpool(void (*destroy)(Req*)) { Reqpool *f; f = emalloc9p(sizeof *f); f->map = allocmap(increqref); f->destroy = destroy; return f; }
Intmap* allocmap(void (*inc)(void*)) { Intmap *m; m = emalloc9p(sizeof(*m)); if(inc == nil) inc = nop; m->inc = inc; return m; }
static CipherState* initrc4(Conn *c, int dir) { CipherState *cs; cs = emalloc9p(sizeof(CipherState)); if(dir) setupRC4state(&cs->state, c->s2cek, 16); else setupRC4state(&cs->state, c->c2sek, 16); return cs; }
void initdata(char *f, int) { char err[ERRMAX]; char buf[1024], *fld[8]; int n; Dir *d; isdev = 1; flash.dfd = open(f, ORDWR); if(flash.dfd < 0){ errstr(err, sizeof err); if((flash.dfd = create(f, ORDWR, 0666)) >= 0){ fprint(2, "warning: created plain file %s\n", buf); goto Plain; } errstr(err, sizeof err); /* restore open error */ sysfatal("opening %s: %r", f); } if(snprint(buf, sizeof buf, "%sctl", f) != strlen(f)+3) sysfatal("path too long: %s", f); flash.cfd = open(buf, ORDWR); if(flash.cfd < 0){ fprint(2, "warning: cannot open %s (%r); assuming plain file\n", buf); Plain: isdev = 0; if(sectsize == 0) sectsize = 512; if(nsects == 0){ if((d = dirstat(f)) == nil) sysfatal("stat %s: %r", f); nsects = d->length / sectsize; free(d); } ones = emalloc9p(sectsize); memset(ones, ~0, sectsize); }else{ n = read(flash.cfd, buf, sizeof(buf)-1); if(n <= 0) sysfatal("reading %sctl: %r", f); buf[n] = 0; n = tokenize(buf, fld, nelem(fld)); if(n < 7) sysfatal("bad flash geometry"); nsects = atoi(fld[5]); sectsize = atoi(fld[6]); if(nsects < 8) sysfatal("unreasonable value for nsects: %lud", nsects); if(sectsize < 512) sysfatal("unreasonable value for sectsize: %lud", sectsize); } }
Pkt * cifshdr(Session *s, Share *sp, int cmd) { Pkt *p; int sign, tid, dfs; dfs = 0; tid = NO_TID; Active = IDLE_TIME; werrstr(""); sign = s->secmode & SECMODE_SIGN_ENABLED? FL2_PACKET_SIGNATURES: 0; if(sp){ tid = sp->tid; // FIXME! if(sp->options & SMB_SHARE_IS_IN_DFS) // FIXME! dfs = FL2_DFS; } p = emalloc9p(sizeof(Pkt) + MTU); memset(p, 0, sizeof(Pkt) +MTU); p->buf = (uchar *)p + sizeof(Pkt); p->s = s; p->request = cmd; /* for debug */ qlock(&s->seqlock); if(s->seqrun){ p->seq = s->seq; s->seq = (s->seq + 2) % 0x10000; } qunlock(&s->seqlock); nbthdr(p); pmem(p, magic, nelem(magic)); p8(p, cmd); pl32(p, 0); /* status (error) */ p8(p, FL_CASELESS_NAMES | FL_CANNONICAL_NAMES); /* flags */ pl16(p, s->flags2 | dfs | sign); /* flags2 */ pl16(p, (s->pid >> 16) & 0xffff); /* PID MS bits */ pl32(p, p->seq); /* MAC / sequence number */ pl32(p, 0); /* MAC */ pl16(p, 0); /* padding */ pl16(p, tid); pl16(p, s->pid & 0xffff); pl16(p, s->uid); pl16(p, s->mid); p->wordbase = p8(p, 0); /* filled in by pbytes() */ return p; }
static int parsepubkey(char *s, RSApub *key, char **sp, int base) { int n; char *host, *p, *z; z = nil; n = strtoul(s, &p, 10); host = nil; if(n < Arbsz || !isspace(*p)){ /* maybe this is a host name */ host = s; s = strpbrk(s, " \t"); if(s == nil) return -1; z = s; *s++ = '\0'; s += strspn(s, " \t"); n = strtoul(s, &p, 10); if(n < Arbsz || !isspace(*p)){ if(z) *z = ' '; return -1; } } /* Arbsz is just a sanity check */ if((key->ek = strtomp(p, &p, base, nil)) == nil || (key->n = strtomp(p, &p, base, nil)) == nil || (*p != '\0' && !isspace(*p)) || mpsignif(key->n) < Arbsz) { mpfree(key->ek); mpfree(key->n); key->ek = nil; key->n = nil; if(z) *z = ' '; return -1; } if(host == nil){ if(*p != '\0'){ p += strspn(p, " \t"); if(*p != '\0'){ host = emalloc9p(strlen(p)+1); strcpy(host, p); } } free(s); } *sp = host; return 0; }
/* * NTLM response only, the LM response is a just * copy of the NTLM one. we do this because the lm * response is easily reversed - Google for l0pht * for more info. */ static Auth * auth_ntlm(char *windom, char *keyp, uchar *chal, int len) { Auth *ap; if((ap = auth_lm_and_ntlm(windom, keyp, chal, len)) == nil) return nil; free(ap->resp[0]); ap->len[0] = ap->len[1]; ap->resp[0] = emalloc9p(ap->len[0]); memcpy(ap->resp[0], ap->resp[1], ap->len[0]); return ap; }
void fscreate(Req *r) { Ramfile *rf; File *f; if(f = createfile(r->fid->file, r->ifcall.name, r->fid->uid, r->ifcall.perm, nil)){ rf = emalloc9p(sizeof *rf); f->aux = rf; r->fid->file = f; r->ofcall.qid = f->qid; respond(r, nil); return; } respond(r, Ebad); }
static CipherState* init3des(Conn *c, int dir) { CipherState *cs; uint8_t key[3][8]; cs = emalloc9p(sizeof(CipherState)); if(dir){ memmove(key, c->s2cek, sizeof key); setupDES3state(&cs->state, key, c->s2civ); } else { memmove(key, c->c2sek, sizeof key); setupDES3state(&cs->state, key, c->c2siv); } return cs; }
void auth9p(Req *r) { char *spec; Afid *afid; afid = emalloc9p(sizeof(Afid)); afid->afd = open("/mnt/factotum/rpc", ORDWR); if(afid->afd < 0) goto error; if((afid->rpc = auth_allocrpc(afid->afd)) == nil) goto error; if(r->ifcall.uname[0] == 0) goto error; afid->uname = estrdup9p(r->ifcall.uname); afid->aname = estrdup9p(r->ifcall.aname); spec = r->srv->keyspec; if(spec == nil) spec = "proto=p9any role=server"; if(auth_rpc(afid->rpc, "start", spec, strlen(spec)) != ARok) goto error; r->afid->qid.type = QTAUTH; r->afid->qid.path = ++authgen; r->afid->qid.vers = 0; r->afid->omode = ORDWR; r->ofcall.qid = r->afid->qid; r->afid->aux = afid; respond(r, nil); return; error: if(afid->rpc) auth_freerpc(afid->rpc); if(afid->uname) free(afid->uname); if(afid->aname) free(afid->aname); if(afid->afd >= 0) close(afid->afd); free(afid); responderror(r); }
void ctlwrite(Req *r) { char *msg; Cmdbuf *cb; r->ofcall.count = r->ifcall.count; msg = emalloc9p(r->ifcall.count+1); memmove(msg, r->ifcall.data, r->ifcall.count); msg[r->ifcall.count] = '\0'; cb = parsecmd(r->ifcall.data, r->ifcall.count); ctlwrite0(r, msg, cb); free(cb); free(msg); }
static char * newpath(char *path, char *name) { char *p, *q; assert((p = strrchr(path, '/')) != nil); if(strcmp(name, "..") == 0){ if(p == path) return estrdup9p("/"); q = emalloc9p((p-path)+1); strecpy(q, q+(p-path)+1, path); return q; } if(strcmp(path, "/") == 0) return smprint("/%s", name); return smprint("%s/%s", path, name); }
static Revlog* getrevlog(Revnode *nd) { char buf[MAXPATH]; Revlog *rl, **link; int mang; mang = mangle; Again: nodepath(seprint(buf, buf+sizeof(buf), "%s/.hg/store/data", workdir), buf+sizeof(buf), nd, mang); link = &revlogs; while(rl = *link){ if(strcmp(buf, rl->path) == 0){ if(rl->ref == 0) nfreerevlogs--; break; } if(nfreerevlogs > 8 && rl->ref == 0){ *link = rl->next; nfreerevlogs--; revlogclose(rl); free(rl); continue; } link = &rl->next; } if(rl == nil){ rl = emalloc9p(sizeof(*rl)); memset(rl, 0, sizeof(*rl)); if(revlogopen(rl, buf, OREAD) < 0){ free(rl); if(mang++ == 0) goto Again; return nil; } rl->next = revlogs; revlogs = rl; if(mang) mangle = 1; } else revlogupdate(rl); incref(rl); return rl; }
Tree* alloctree(char *uid, char *gid, uint32_t mode, void (*destroy)(File*)) { char *muid; Tree *t; File *f; t = emalloc9p(sizeof *t); f = allocfile(); f->Dir.name = estrdup9p("/"); if(uid == nil){ uid = getuser(); if(uid == nil) uid = "none"; } uid = estrdup9p(uid); if(gid == nil) gid = estrdup9p(uid); else gid = estrdup9p(gid); muid = estrdup9p(uid); f->Dir.qid = (Qid){0, 0, QTDIR}; f->Dir.length = 0; f->Dir.atime = f->Dir.mtime = time(0); f->Dir.mode = DMDIR | mode; f->tree = t; f->parent = f; f->Dir.uid = uid; f->Dir.gid = gid; f->Dir.muid = muid; incref(&f->Ref); t->root = f; t->qidgen = 0; t->dirqidgen = 1; if(destroy == nil) destroy = nop; t->destroy = destroy; return t; }
Req* allocreq(Reqpool *pool, ulong tag) { Req *r; r = emalloc9p(sizeof *r); r->tag = tag; r->pool = pool; increqref(r); increqref(r); if(caninsertkey(pool->map, tag, r) == 0) { closereq(r); closereq(r); return nil; } return r; }
void main(int argc, char **argv) { int ro; char *file, *mount; mount = "/n/brzr"; ro = 0; file = "/dev/flash/fs"; ARGBEGIN { case 'D': chatty9p++; break; case 'r': ro++; break; case 'n': nsects = argval(ARGF()); break; case 'z': sectsize = argval(ARGF()); break; case 'f': file = ARGF(); break; case 'm': mount = ARGF(); break; default: usage(); } ARGEND if(argc != 0) usage(); initdata(file, 0); sectbuff = emalloc9p(sectsize); einit(); loadfs(ro); serve(mount); exits(nil); }
Session * cifsdial(char *host, char *called, char *sysname) { int nbt, fd; char *addr; Session *s; if(Debug) fprint(2, "cifsdial: host=%s called=%s sysname=%s\n", host, called, sysname); if((addr = netmkaddr(host, "tcp", "cifs")) == nil) return nil; nbt = 0; if((fd = dial(addr, nil, nil, nil)) == -1){ nbt = 1; if((fd = nbtdial(host, called, sysname)) == -1) return nil; } s = emalloc9p(sizeof(Session)); memset(s, 0, sizeof(Session)); s->fd = fd; s->nbt = nbt; s->mtu = MTU; s->pid = getpid(); s->mid = time(nil) ^ getpid(); s->uid = NO_UID; 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->macidx = -1; if(s->mtu > MTU) s->mtu = MTU; return s; }