int loadbloom(Bloom *b) { int i, n; uint ones; uchar *data; u32int *a; data = vtmallocz(b->size); if(readpart(b->part, 0, data, b->size) < 0){ vtfree(b); vtfree(data); return -1; } b->data = data; a = (u32int*)b->data; n = b->size/4; ones = 0; for(i=0; i<n; i++) ones += countbits(a[i]); addstat(StatBloomOnes, ones); if(b->size == MaxBloomSize) /* 2^32 overflows ulong */ addstat(StatBloomBits, b->size*8-1); else addstat(StatBloomBits, b->size*8); return 0; }
static vlong findintoc(HConnect *c, Arena *arena, uchar *score) { uchar *blk; int i; vlong off; vlong coff; ClumpInfo ci; blk = vtmalloc(arena->blocksize); off = arena->base + arena->size; coff = 0; for(i=0; i<arena->memstats.clumps; i++){ if(i%arena->clumpmax == 0){ off -= arena->blocksize; if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){ if(c) hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n", off); break; } } unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize); if(scorecmp(ci.score, score) == 0){ vtfree(blk); return coff; } coff += ClumpSize + ci.size; } vtfree(blk); return -1; }
void deeClose(DirEntryEnum *dee) { int i; if(dee == nil) return; for(i=dee->i; i<dee->n; i++) deCleanup(dee->buf+i); vtfree(dee->buf); fileDecRef(dee->file); vtfree(dee); }
int main(int argc, char *argv[]) { struct vt vt ALIGNED(CLSIZE); // struct vt *vt; long nrow; long ncol; // long nbufrow; memset(&vt, 0, sizeof(struct vt)); vtgetopt(&vt, argc, argv); if (!vtinit(&vt, argc, argv)) { fprintf(stderr, "failed to initialise VT\n"); exit(1); } #if 0 nbufrow = vt.textbuf.nrow; if (!nbufrow) { nbufnrow = VTDEFBUFNROW; } #endif ncol = vt.state.ncol; if (!ncol) { ncol = VTDEFNCOL; vt.state.ncol = ncol; } nrow = vt.state.nrow; if (!nrow) { nrow = VTDEFNROW; vt.state.nrow = nrow; } if (!uiinittextbuf(&vt.textbuf, nrow, ncol, 0)) { vtfree(&vt); exit(1); } vtprintinfo(&vt); #if 0 vt.state.nrow = 24; vt.state.ncol = 80; vt.textbuf.nrow = VTDEFBUFNROW; vt.textbuf.nrow = 24; #endif vt.state.w = vt.state.ncol * vt.font.boxw; vt.state.h = vt.state.nrow * vt.font.boxh; vtfree(&vt); exit(1); }
/* * load clump info group information by scanning entire toc. */ static void loadcig(Arena *arena) { uint32_t i, j, ncig, nci; ArenaCIG *cig; ClumpInfo *ci; uint64_t offset; int ms; if(arena->cig || arena->ncig < 0) return; // fprint(2, "loadcig %s\n", arena->name); ncig = (arena->memstats.clumps+ArenaCIGSize-1) / ArenaCIGSize; if(ncig == 0){ arena->cig = vtmalloc(1); arena->ncig = 0; return; } ms = msec(); cig = vtmalloc(ncig*sizeof cig[0]); ci = vtmalloc(ArenaCIGSize*sizeof ci[0]); offset = 0; for(i=0; i<ncig; i++){ nci = readclumpinfos(arena, i*ArenaCIGSize, ci, ArenaCIGSize); cig[i].offset = offset; for(j=0; j<nci; j++) offset += ClumpSize + ci[j].size; if(nci < ArenaCIGSize){ if(i != ncig-1){ vtfree(ci); vtfree(cig); arena->ncig = -1; fprint(2, "loadcig %s: got %ud cigs, expected %ud\n", arena->name, i+1, ncig); goto out; } } } vtfree(ci); arena->ncig = ncig; arena->cig = cig; out: ms = msec() - ms; addstat2(StatCigLoad, 1, StatCigLoadTime, ms); }
void vtrespond(VtReq *r) { Packet *p; VtSconn *sc; sc = r->sc; if(r->rx.tag != r->tx.tag) abort(); if(r->rx.msgtype != r->tx.msgtype+1 && r->rx.msgtype != VtRerror) abort(); if(chattyventi) fprint(2, "%s -> %F\n", argv0, &r->rx); if((p = vtfcallpack(&r->rx)) == nil){ vtlog(VtServerLog, "%s: vtfcallpack %F: %r<br>\n", sc->c->addr, &r->rx); fprint(2, "fcallpack on %s: %r\n", sc->dir); packetfree(p); vtfcallclear(&r->rx); return; } vtlog(VtServerLog, "<font size=-1>%T %s:</font> send packet %p (%F)<br>\n", sc->c->addr, p, &r->rx); if(vtsend(sc->c, p) < 0) fprint(2, "vtsend %F: %r\n", &r->rx); scdecref(sc); vtfcallclear(&r->tx); vtfcallclear(&r->rx); vtfree(r); }
int fileMetaFlush(File *f, int rec) { File **kids, *p; int nkids; int i, rv; fileMetaLock(f); rv = fileMetaFlush2(f, nil); fileMetaUnlock(f); if(!rec || !fileIsDir(f)) return rv; if(!fileLock(f)) return rv; nkids = 0; for(p=f->down; p; p=p->next) nkids++; kids = vtmalloc(nkids*sizeof(File*)); i = 0; for(p=f->down; p; p=p->next){ kids[i++] = p; p->ref++; } fileUnlock(f); for(i=0; i<nkids; i++){ rv |= fileMetaFlush(kids[i], 1); fileDecRef(kids[i]); } vtfree(kids); return rv; }
Bloom* readbloom(Part *p) { uchar buf[512]; Bloom *b; b = vtmallocz(sizeof *b); if(readpart(p, 0, buf, sizeof buf) < 0) return nil; /* * pass buf as b->data so that bloominit * can parse header. won't be used for * accessing bits (cleared below). */ if(bloominit(b, 0, buf) < 0){ vtfree(b); return nil; }else{ /* * default block size is system page size. * the bloom filter is usually very big. * bump the block size up to speed i/o. */ if(p->blocksize < (1<<20)){ p->blocksize = 1<<20; if(p->blocksize > p->size) p->blocksize = p->size; } } b->part = p; b->data = nil; return b; }
static void fileFree(File *f) { sourceClose(f->source); sourceClose(f->msource); deCleanup(&f->dir); memset(f, ~0, sizeof(File)); vtfree(f); }
static void scdecref(VtSconn *sc) { qlock(&sc->lk); if(--sc->ref > 0){ qunlock(&sc->lk); return; } if(sc->c) vtfreeconn(sc->c); vtfree(sc); }
void vtfreeconn(VtConn *z) { vthangup(z); qlock(&z->lk); /* * Wait for send and recv procs to notice * the hangup and clear out the queues. */ while(z->readq || z->writeq){ if(z->readq) _vtqhangup(z->readq); if(z->writeq) _vtqhangup(z->writeq); rsleep(&z->rpcfork); } packetfree(z->part); vtfree(z->version); vtfree(z->sid); qunlock(&z->lk); vtfree(z); }
static int deeFill(DirEntryEnum *dee) { int i, n; Source *meta, *source; MetaBlock mb; MetaEntry me; File *f; Block *b; DirEntry *de; /* clean up first */ for(i=dee->i; i<dee->n; i++) deCleanup(dee->buf+i); vtfree(dee->buf); dee->buf = nil; dee->i = 0; dee->n = 0; f = dee->file; source = f->source; meta = f->msource; b = sourceBlock(meta, dee->boff, OReadOnly); if(b == nil) goto Err; if(!mbUnpack(&mb, b->data, meta->dsize)) goto Err; n = mb.nindex; dee->buf = vtmalloc(n * sizeof(DirEntry)); for(i=0; i<n; i++){ de = dee->buf + i; meUnpack(&me, &mb, i); if(!deUnpack(de, &me)) goto Err; dee->n++; if(!(de->mode & ModeDir)) if(!dirEntrySize(source, de->entry, de->gen, &de->size)) goto Err; } dee->boff++; blockPut(b); return 1; Err: blockPut(b); return 0; }
char * rclunk(Fid *f) { f->busy = 0; f->open = 0; vtfree(f->user); f->user = nil; if(f->file) vacfiledecref(f->file); f->file = nil; vdeclose(f->vde); f->vde = nil; return 0; }
int vtsrvhello(VtConn *z) { VtFcall tx, rx; Packet *p; if((p = vtrecv(z)) == nil) return -1; if(vtfcallunpack(&tx, p) < 0){ packetfree(p); return -1; } packetfree(p); if(tx.msgtype != VtThello){ vtfcallclear(&tx); werrstr("bad packet type %d; want Thello %d", tx.msgtype, VtThello); return -1; } if(tx.tag != 0){ vtfcallclear(&tx); werrstr("bad tag in hello"); return -1; } if(strcmp(tx.version, z->version) != 0){ vtfcallclear(&tx); werrstr("bad version in hello"); return -1; } vtfree(z->uid); z->uid = tx.uid; tx.uid = nil; vtfcallclear(&tx); memset(&rx, 0, sizeof rx); rx.msgtype = VtRhello; rx.tag = tx.tag; rx.sid = "anonymous"; if((p = vtfcallpack(&rx)) == nil) return -1; if(vtsend(z, p) < 0) return -1; return 0; }
void vtfileclose(VtFile *r) { if(r == nil) return; qlock(&r->lk); r->ref--; if(r->ref){ qunlock(&r->lk); return; } assert(r->ref == 0); qunlock(&r->lk); if(r->parent) vtfileclose(r->parent); memset(r, ~0, sizeof(*r)); vtfree(r); }
void vtloghlist(Hio *h) { char **p; int i, n; hprint(h, "<html><head>\n"); hprint(h, "<title>Venti Server Logs</title>\n"); hprint(h, "</head><body>\n"); hprint(h, "<b>Venti Server Logs</b>\n<p>\n"); p = vtlognames(&n); qsort(p, n, sizeof(p[0]), strpcmp); for(i=0; i<n; i++) hprint(h, "<a href=\"/log?log=%s\">%s</a><br>\n", p[i], p[i]); vtfree(p); hprint(h, "</body></html>\n"); }
void io(void) { char *err; int n; for(;;){ n = read9pmsg(mfd[0], mdata, sizeof mdata); if(n <= 0) break; if(convM2S(mdata, n, &rhdr) != n) sysfatal("convM2S conversion error"); if(dflag) fprint(2, "vacfs:<-%F\n", &rhdr); thdr.data = (char*)mdata + IOHDRSZ; if(!fcalls[rhdr.type]) err = "bad fcall type"; else err = (*fcalls[rhdr.type])(newfid(rhdr.fid)); if(err){ thdr.type = Rerror; thdr.ename = err; #ifdef PLAN9PORT thdr.errornum = 0; #endif }else{ thdr.type = rhdr.type + 1; thdr.fid = rhdr.fid; } thdr.tag = rhdr.tag; if(dflag) fprint(2, "vacfs:->%F\n", &thdr); n = convS2M(&thdr, mdata, messagesize); if(n <= BIT16SZ) sysfatal("convS2M conversion error"); if(err) vtfree(err); if(write(mfd[1], mdata, n) != n) sysfatal("mount write: %r"); } }
/* * f->source and f->msource must NOT be locked. * see fileMetaLock. */ static void fileWAccess(File* f, char *mid) { if(f->mode == OReadOnly) return; fileMetaLock(f); f->dir.atime = f->dir.mtime = time(0L); if(strcmp(f->dir.mid, mid) != 0){ vtfree(f->dir.mid); f->dir.mid = vtstrdup(mid); } f->dir.mcount++; f->dirty = 1; fileMetaUnlock(f); /*RSC: let's try this */ /*presotto - lets not if(f->up) fileWAccess(f->up, mid); */ }
static char* readap(Part *p, ArenaPart *ap) { uchar *blk; char *table; blk = vtmalloc(8192); if(readpart(p, PartBlank, blk, 8192) != 8192) return nil; if(unpackarenapart(ap, blk) < 0){ werrstr("corrupt arena part header: %r"); return nil; } vtfree(blk); ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1); ap->tabsize = ap->arenabase - ap->tabbase; table = vtmalloc(ap->tabsize+1); if(readpart(p, ap->tabbase, (uchar*)table, ap->tabsize) != ap->tabsize){ werrstr("reading arena part directory: %r"); return nil; } table[ap->tabsize] = 0; return table; }
struct vt * vtinit(struct vt *vt, int argc, char *argv[]) { long newvt = (vt) ? 0 : 1; void *ptr; if (!vt) { vt = calloc(1, sizeof(struct vt)); if (!vt) { return NULL; } } vt->atr.fd = -1; if (!vtinitbuf(vt) || !vtinitpty(vt)) { vtfree(vt); if (newvt) { free(vt); } return NULL; } vt->state.mode = VTDEFMODE; vt->state.fgcolor = VTDEFFGCOLOR; vt->state.bgcolor = VTDEFBGCOLOR; vt->state.textatr = VTDEFTEXTATR; uisetsys(&vt->ui, UI_SYS_XORG); uiinit(&vt->ui, argc, argv); if (!vtinitcolors(vt)) { vtfree(vt); if (newvt) { free(vt); } return NULL; } if (!vtinitfonts(vt)) { vtfree(vt); if (newvt) { free(vt); } return NULL; } ptr = calloc(rounduppow2(vt->state.ncol, 32) >> 5, sizeof(uint32_t)); if (!ptr) { vtfree(vt); if (newvt) { free(vt); } return NULL; } vt->state.tabmap = ptr; vtinitesc(vt); vt->state.scrolltop = 0; vt->state.scrollbottom = vt->state.ncol - 1; return vt; }
static void periodicFree(Periodic *p) { vtfree(p); }
static int diskarenapart(HConnect *c, char *disk, Part *p) { char *arenaname; ArenaPart ap; ArenaHead head; Arena arena; char *table; char *score; char *clump; uchar *blk; vlong start, end, off; char tbuf[60]; hprint(&c->hout, "<h1>arena partition %s</h1>\n", disk); if((table = readap(p, &ap)) == nil){ hprint(&c->hout, "%r\n"); goto out; } hprint(&c->hout, "<pre>\n"); hprint(&c->hout, "version=%d blocksize=%d base=%d\n", ap.version, ap.blocksize, ap.arenabase); hprint(&c->hout, "</pre>\n"); arenaname = hargstr(c, "arena", ""); if(arenaname[0] == 0){ diskarenatable(c, disk, table); goto out; } if(xfindarena(table, arenaname, &start, &end) < 0){ hprint(&c->hout, "no such arena %s\n", arenaname); goto out; } hprint(&c->hout, "<h2>arena %s</h2>\n", arenaname); hprint(&c->hout, "<pre>start=%#llx end=%#llx<pre>\n", start, end); if(end < start || end - start < HeadSize){ hprint(&c->hout, "bad size %#llx\n", end - start); goto out; } // read arena header, tail blk = vtmalloc(HeadSize); if(readpart(p, start, blk, HeadSize) != HeadSize){ hprint(&c->hout, "reading header: %r\n"); vtfree(blk); goto out; } if(unpackarenahead(&head, blk) < 0){ hprint(&c->hout, "corrupt arena header: %r\n"); // hhex(blk, HeadSize); vtfree(blk); goto out; } vtfree(blk); hprint(&c->hout, "head:\n<pre>\n"); hprint(&c->hout, "version=%d name=%s blocksize=%d size=%#llx clumpmagic=%#ux\n", head.version, head.name, head.blocksize, head.size, head.clumpmagic); hprint(&c->hout, "</pre><br><br>\n"); if(head.blocksize > MaxIoSize || head.blocksize >= end - start){ hprint(&c->hout, "corrupt block size %d\n", head.blocksize); goto out; } blk = vtmalloc(head.blocksize); if(readpart(p, end - head.blocksize, blk, head.blocksize) < 0){ hprint(&c->hout, "reading tail: %r\n"); vtfree(blk); goto out; } memset(&arena, 0, sizeof arena); arena.part = p; arena.blocksize = head.blocksize; arena.clumpmax = head.blocksize / ClumpInfoSize; arena.base = start + head.blocksize; arena.size = end - start - 2 * head.blocksize; if(unpackarena(&arena, blk) < 0){ vtfree(blk); goto out; } scorecp(arena.score, blk+head.blocksize - VtScoreSize); vtfree(blk); hprint(&c->hout, "tail:\n<pre>\n"); hprint(&c->hout, "version=%d name=%s\n", arena.version, arena.name); hprint(&c->hout, "ctime=%d %s\n", arena.ctime, fmttime(tbuf, arena.ctime)); hprint(&c->hout, "wtime=%d %s\n", arena.wtime, fmttime(tbuf, arena.wtime)); hprint(&c->hout, "clumpmagic=%#ux\n", arena.clumpmagic); hprint(&c->hout, "score %V\n", arena.score); hprint(&c->hout, "diskstats:\n"); hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n", arena.diskstats.clumps, arena.diskstats.cclumps, arena.diskstats.used, arena.diskstats.uncsize, arena.diskstats.sealed); hprint(&c->hout, "memstats:\n"); hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n", arena.memstats.clumps, arena.memstats.cclumps, arena.memstats.used, arena.memstats.uncsize, arena.memstats.sealed); if(arena.clumpmax == 0){ hprint(&c->hout, "bad clumpmax\n"); goto out; } score = hargstr(c, "score", ""); clump = hargstr(c, "clump", ""); if(clump[0]){ off = strtoull(clump, 0, 0); diskarenaclump(c, &arena, off, score[0] ? score : nil); }else if(score[0]){ diskarenaclump(c, &arena, -1, score); }else{ diskarenatoc(c, &arena); } out: free(table); return 0; }
static int diskarenaclump(HConnect *c, Arena *arena, vlong off, char *scorestr) { uchar *blk, *blk2; Clump cl; char err[ERRMAX]; uchar xscore[VtScoreSize], score[VtScoreSize]; Unwhack uw; int n; if(scorestr){ if(vtparsescore(scorestr, nil, score) < 0){ hprint(&c->hout, "bad score %s: %r\n", scorestr); return -1; } if(off < 0){ off = findintoc(c, arena, score); if(off < 0){ hprint(&c->hout, "score %V not found in arena %s\n", score, arena->name); return -1; } hprint(&c->hout, "score %V at %#llx\n", score, off); } }else memset(score, 0, sizeof score); if(off < 0){ hprint(&c->hout, "bad offset %#llx\n", off); return -1; } off += arena->base; blk = vtmalloc(ClumpSize + VtMaxLumpSize); if(readpart(arena->part, off, blk, ClumpSize + VtMaxLumpSize) != ClumpSize + VtMaxLumpSize){ hprint(&c->hout, "reading at %#llx: %r\n", off); vtfree(blk); return -1; } if(unpackclump(&cl, blk, arena->clumpmagic) < 0){ hprint(&c->hout, "unpackclump: %r\n<br>"); rerrstr(err, sizeof err); if(strstr(err, "magic")){ hprint(&c->hout, "trying again with magic=%#ux<br>\n", U32GET(blk)); if(unpackclump(&cl, blk, U32GET(blk)) < 0){ hprint(&c->hout, "unpackclump: %r\n<br>\n"); goto error; } }else goto error; } hprint(&c->hout, "<pre>type=%d size=%d uncsize=%d score=%V\n", cl.info.type, cl.info.size, cl.info.uncsize, cl.info.score); hprint(&c->hout, "encoding=%d creator=%d time=%d %s</pre>\n", cl.encoding, cl.creator, cl.time, fmttime(err, cl.time)); if(cl.info.type == VtCorruptType) hprint(&c->hout, "clump is marked corrupt<br>\n"); if(cl.info.size >= VtMaxLumpSize){ hprint(&c->hout, "clump too big\n"); goto error; } switch(cl.encoding){ case ClumpECompress: blk2 = vtmalloc(VtMaxLumpSize); unwhackinit(&uw); n = unwhack(&uw, blk2, cl.info.uncsize, blk+ClumpSize, cl.info.size); if(n < 0){ hprint(&c->hout, "decompression failed\n"); vtfree(blk2); goto error; } if(n != cl.info.uncsize){ hprint(&c->hout, "got wrong amount: %d wanted %d\n", n, cl.info.uncsize); // hhex(blk2, n); vtfree(blk2); goto error; } scoremem(xscore, blk2, cl.info.uncsize); vtfree(blk2); break; case ClumpENone: scoremem(xscore, blk+ClumpSize, cl.info.size); break; } hprint(&c->hout, "score=%V<br>\n", xscore); if(scorestr && scorecmp(score, xscore) != 0) hprint(&c->hout, "score does NOT match expected %V\n", score); vtfree(blk); return 0; error: // hhex(blk, ClumpSize + VtMaxLumpSize); vtfree(blk); return -1; }
/* * allocate space for the clump and write it, * updating the arena directory ZZZ question: should this distinguish between an arena filling up and real errors writing the clump? */ uint64_t writeaclump(Arena *arena, Clump *c, uint8_t *clbuf) { DBlock *b; uint64_t a, aa; uint32_t clump, n, nn, m, off, blocksize; int ok; n = c->info.size + ClumpSize + U32Size; qlock(&arena->lock); aa = arena->memstats.used; if(arena->memstats.sealed || aa + n + U32Size + arenadirsize(arena, arena->memstats.clumps + 1) > arena->size){ if(!arena->memstats.sealed){ logerr(EOk, "seal memstats %s", arena->name); arena->memstats.sealed = 1; wbarena(arena); } qunlock(&arena->lock); return TWID64; } if(packclump(c, &clbuf[0], arena->clumpmagic) < 0){ qunlock(&arena->lock); return TWID64; } /* * write the data out one block at a time */ blocksize = arena->blocksize; a = arena->base + aa; off = a & (blocksize - 1); a -= off; nn = 0; for(;;){ b = getdblock(arena->part, a, off != 0 ? ORDWR : OWRITE); if(b == nil){ qunlock(&arena->lock); return TWID64; } dirtydblock(b, DirtyArena); m = blocksize - off; if(m > n - nn) m = n - nn; memmove(&b->data[off], &clbuf[nn], m); ok = 0; putdblock(b); if(ok < 0){ qunlock(&arena->lock); return TWID64; } nn += m; if(nn == n) break; off = 0; a += blocksize; } arena->memstats.used += c->info.size + ClumpSize; arena->memstats.uncsize += c->info.uncsize; if(c->info.size < c->info.uncsize) arena->memstats.cclumps++; clump = arena->memstats.clumps; if(clump % ArenaCIGSize == 0){ if(arena->cig == nil){ loadcig(arena); if(arena->cig == nil) goto NoCIG; } /* add aa as start of next cig */ if(clump/ArenaCIGSize != arena->ncig){ fprint(2, "bad arena cig computation %s: writing clump %d but %d cigs\n", arena->name, clump, arena->ncig); arena->ncig = -1; vtfree(arena->cig); arena->cig = nil; goto NoCIG; } arena->cig = vtrealloc(arena->cig, (arena->ncig+1)*sizeof arena->cig[0]); arena->cig[arena->ncig++].offset = aa; } NoCIG: arena->memstats.clumps++; if(arena->memstats.clumps == 0) sysfatal("clumps wrapped"); arena->wtime = now(); if(arena->ctime == 0) arena->ctime = arena->wtime; writeclumpinfo(arena, clump, &c->info); wbarena(arena); qunlock(&arena->lock); return aa; }
void qfree(Queue *q) { vtfree(q); }
int fileSetDir(File *f, DirEntry *dir, char *uid) { File *ff; char *oelem; u32int mask; u64int size; /* can not set permissions for the root */ if(fileIsRoot(f)){ werrstr(ERoot); return 0; } if(!fileLock(f)) return 0; if(f->source->mode != OReadWrite){ werrstr(EReadOnly); fileUnlock(f); return 0; } fileMetaLock(f); /* check new name does not already exist */ if(strcmp(f->dir.elem, dir->elem) != 0){ for(ff = f->up->down; ff; ff=ff->next){ if(strcmp(dir->elem, ff->dir.elem) == 0 && !ff->removed){ werrstr(EExists); goto Err; } } ff = dirLookup(f->up, dir->elem); if(ff != nil){ fileDecRef(ff); werrstr(EExists); goto Err; } } if(!sourceLock2(f->source, f->msource, -1)) goto Err; if(!fileIsDir(f)){ size = sourceGetSize(f->source); if(size != dir->size){ if(!sourceSetSize(f->source, dir->size)){ sourceUnlock(f->source); if(f->msource) sourceUnlock(f->msource); goto Err; } /* commited to changing it now */ } } /* commited to changing it now */ if((f->dir.mode&ModeTemporary) != (dir->mode&ModeTemporary)) fileSetTmp(f, dir->mode&ModeTemporary); sourceUnlock(f->source); if(f->msource) sourceUnlock(f->msource); oelem = nil; if(strcmp(f->dir.elem, dir->elem) != 0){ oelem = f->dir.elem; f->dir.elem = vtstrdup(dir->elem); } if(strcmp(f->dir.uid, dir->uid) != 0){ vtfree(f->dir.uid); f->dir.uid = vtstrdup(dir->uid); } if(strcmp(f->dir.gid, dir->gid) != 0){ vtfree(f->dir.gid); f->dir.gid = vtstrdup(dir->gid); } f->dir.mtime = dir->mtime; f->dir.atime = dir->atime; //fprint(2, "mode %x %x ", f->dir.mode, dir->mode); mask = ~(ModeDir|ModeSnapshot); f->dir.mode &= ~mask; f->dir.mode |= mask & dir->mode; f->dirty = 1; //fprint(2, "->%x\n", f->dir.mode); fileMetaFlush2(f, oelem); vtfree(oelem); fileMetaUnlock(f); fileUnlock(f); fileWAccess(f->up, uid); return 1; Err: fileMetaUnlock(f); fileUnlock(f); return 0; }
static void connproc(void *v) { VtSconn *sc; VtConn *c; Packet *p; VtReq *r; int fd; static int first=1; if(first && chattyventi){ first=0; fmtinstall('F', vtfcallfmt); } r = nil; sc = v; sc->c = nil; if(0) fprint(2, "new call %s on %d\n", sc->dir, sc->ctl); fd = accept(sc->ctl, sc->dir); close(sc->ctl); if(fd < 0){ fprint(2, "accept %s: %r\n", sc->dir); goto out; } c = vtconn(fd, fd); sc->c = c; if(vtversion(c) < 0){ fprint(2, "vtversion %s: %r\n", sc->dir); goto out; } if(vtsrvhello(c) < 0){ fprint(2, "vtsrvhello %s: %r\n", sc->dir); goto out; } if(0) fprint(2, "new proc %s\n", sc->dir); proccreate(vtsendproc, c, STACK); qlock(&c->lk); while(!c->writeq) rsleep(&c->rpcfork); qunlock(&c->lk); while((p = vtrecv(c)) != nil){ r = vtmallocz(sizeof(VtReq)); if(vtfcallunpack(&r->tx, p) < 0){ vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv bad packet %p: %r<br>\n", c->addr, p); fprint(2, "bad packet on %s: %r\n", sc->dir); packetfree(p); continue; } vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv packet %p (%F)<br>\n", c->addr, p, &r->tx); if(chattyventi) fprint(2, "%s <- %F\n", argv0, &r->tx); packetfree(p); if(r->tx.msgtype == VtTgoodbye) break; r->rx.tag = r->tx.tag; r->sc = sc; scincref(sc); if(_vtqsend(sc->srv->q, r) < 0){ scdecref(sc); fprint(2, "hungup queue\n"); break; } r = nil; } if(0) fprint(2, "eof on %s\n", sc->dir); out: if(r){ vtfcallclear(&r->tx); vtfree(r); } if(0) fprint(2, "freed %s\n", sc->dir); scdecref(sc); return; }
Packet* _vtrpc(VtConn *z, Packet *p, VtFcall *tx) { int i; uchar tag, buf[2], *top; Rwait *r, *rr; /* must malloc because stack could be private */ r = vtmallocz(sizeof(Rwait)); qlock(&z->lk); r->r.l = &z->lk; tag = gettag(z, r); if(tx){ /* vtfcallrpc can't print packet because it doesn't have tag */ tx->tag = tag; if(chattyventi) fprint(2, "%s -> %F\n", argv0, tx); } /* slam tag into packet */ top = packetpeek(p, buf, 0, 2); if(top == nil){ packetfree(p); return nil; } if(top == buf){ werrstr("first two bytes must be in same packet fragment"); packetfree(p); vtfree(r); return nil; } top[1] = tag; qunlock(&z->lk); if(vtsend(z, p) < 0){ vtfree(r); return nil; } qlock(&z->lk); /* wait for the muxer to give us our packet */ r->sleeping = 1; z->nsleep++; while(z->muxer && !r->done) rsleep(&r->r); z->nsleep--; r->sleeping = 0; /* if not done, there's no muxer: start muxing */ if(!r->done){ if(z->muxer) abort(); z->muxer = 1; while(!r->done){ qunlock(&z->lk); if((p = vtrecv(z)) == nil){ werrstr("unexpected eof on venti connection"); z->muxer = 0; vtfree(r); return nil; } qlock(&z->lk); muxrpc(z, p); } z->muxer = 0; /* if there is anyone else sleeping, wake first unfinished to mux */ if(z->nsleep) for(i=0; i<256; i++){ rr = z->wait[i]; if(rr && rr->sleeping && !rr->done){ rwakeup(&rr->r); break; } } } p = r->p; puttag(z, r, tag); vtfree(r); qunlock(&z->lk); return p; }
int authCheck(Fcall* t, Fid* fid, Fsys* fsys) { Con *con; Fid *afid; uchar buf[1]; /* * Can't lookup with FidWlock here as there may be * protocol to do. Use a separate lock to protect altering * the auth information inside afid. */ con = fid->con; if(t->afid == NOFID){ /* * If no authentication is asked for, allow * "none" provided the connection has already * been authenticatated. * * The console is allowed to attach without * authentication. */ rlock(&con->alock); if(con->isconsole){ /* anything goes */ }else if((con->flags&ConNoneAllow) || con->aok){ static int noneprint; if(noneprint++ < 10) consPrint("attach %s as %s: allowing as none\n", fsysGetName(fsys), fid->uname); vtfree(fid->uname); fid->uname = vtstrdup(unamenone); }else{ runlock(&con->alock); consPrint("attach %s as %s: connection not authenticated, not console\n", fsysGetName(fsys), fid->uname); werrstr("cannot attach as none before authentication"); return 0; } runlock(&con->alock); if((fid->uid = uidByUname(fid->uname)) == nil){ consPrint("attach %s as %s: unknown uname\n", fsysGetName(fsys), fid->uname); werrstr("unknown user"); return 0; } return 1; } if((afid = fidGet(con, t->afid, 0)) == nil){ consPrint("attach %s as %s: bad afid\n", fsysGetName(fsys), fid->uname); werrstr("bad authentication fid"); return 0; } /* * Check valid afid; * check uname and aname match. */ if(!(afid->qid.type & QTAUTH)){ consPrint("attach %s as %s: afid not an auth file\n", fsysGetName(fsys), fid->uname); fidPut(afid); werrstr("bad authentication fid"); return 0; } if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){ consPrint("attach %s as %s: afid is for %s as %s\n", fsysGetName(fsys), fid->uname, fsysGetName(afid->fsys), afid->uname); fidPut(afid); werrstr("attach/auth mismatch"); return 0; } qlock(&afid->alock); if(afid->cuname == nil){ if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){ qunlock(&afid->alock); consPrint("attach %s as %s: %r\n", fsysGetName(fsys), fid->uname); fidPut(afid); werrstr("fossil authCheck: auth protocol not finished"); return 0; } } qunlock(&afid->alock); assert(fid->uid == nil); if((fid->uid = uidByUname(afid->cuname)) == nil){ consPrint("attach %s as %s: unknown cuname %s\n", fsysGetName(fsys), fid->uname, afid->cuname); fidPut(afid); werrstr("unknown user"); return 0; } vtfree(fid->uname); fid->uname = vtstrdup(afid->cuname); fidPut(afid); /* * Allow "none" once the connection has been authenticated. */ wlock(&con->alock); con->aok = 1; wunlock(&con->alock); return 1; }
struct vt * vtrun(struct vt *vt) { char *path; struct vtbuf *buf; // pid_t pid; if (!vt) { vt = malloc(sizeof(struct vt)); } // vt-> = vt; /* set signals up */ vtsetsigs(); /* * set input field separator for shell to TAB for old shells that don't * reset it. This is for security reasons to prevent users from setting * IFS to make system() execute a different program. */ putenv("IFS= \t"); /* export terminal type */ putenv("TERM=vt100"); /* allocate buffer */ buf = calloc(1, sizeof(struct vtbuf)); if (!buf) { vtfree(vt); fprintf(stderr, "out of memory\n"); exit(1); } vt->buf = buf; /* allocate and read path */ path = malloc(PATH_MAX); if (!path) { vtfree(vt); fprintf(stderr, "out of memory\n"); exit(1); } if (!getcwd(path, PATH_MAX)) { vtfree(vt); free(path); fprintf(stderr, "out of memory\n"); exit(1); } vt->path = path; /* initialise desktop connection */ vtinitconn(vt); /* initialise terminal screens */ if (!vtinitscr(vt, TERMNSCREEN)) { vtfree(vt); free(path); exit(1); } /* initialise terminal windows */ if (!vtinitwin(vt)) { vtfree(vt); free(path); vtfreescr(vt); exit(1); } /* map terminal windows */ vtmapwin(vt); /* synchronize desktop */ vtsyncwin(vt); return vt; }