예제 #1
0
파일: plan9-thread.c 프로젝트: npe9/harvey
void
vtAttach(void)
{
	int pid;
	Thread *p;
	static int init;
	static Lock lk;

	lock(&lk);
	if(!init) {
		rfork(RFREND);
		vtThreadInit();
		init = 1;
	}
	unlock(&lk);

	pid = getpid();
	p = *vtRock;
	if(p != nil && p->pid == pid) {
		p->ref++;
		return;
	}
	p = vtMemAllocZ(sizeof(Thread));
	p->ref = 1;
	p->pid = pid;
	*vtRock = p;
}
예제 #2
0
파일: plan9-thread.c 프로젝트: npe9/harvey
VtRendez*
vtRendezAlloc(VtLock *p)
{
	VtRendez *q;

	q = vtMemAllocZ(sizeof(VtRendez));
	q->lk = p;
	setmalloctag(q, getcallerpc(&p));
	return q;
}
예제 #3
0
파일: 9user.c 프로젝트: 99years/plan9
static User*
userAlloc(char* uid, char* uname)
{
	User *u;

	u = vtMemAllocZ(sizeof(User));
	u->uid = vtStrDup(uid);
	u->uname = vtStrDup(uname);

	return u;
}
예제 #4
0
파일: 9excl.c 프로젝트: CoryXie/nix-os
int
exclAlloc(Fid* fid)
{
	ulong t;
	Excl *excl;

	assert(fid->excl == nil);

	t = time(0L);
	vtLock(ebox.lock);
	for(excl = ebox.head; excl != nil; excl = excl->next){
		if(excl->fsys != fid->fsys || excl->path != fid->qid.path)
			continue;
		/*
		 * Found it.
		 * Now, check if it's timed out.
		 * If not, return error, it's locked.
		 * If it has timed out, zap the old
		 * one and continue on to allocate a
		 * a new one.
		 */
		if(excl->time >= t){
			vtUnlock(ebox.lock);
			vtSetError("exclusive lock");
			return 0;
		}
		excl->fsys = nil;
	}

	/*
	 * Not found or timed-out.
	 * Alloc a new one and initialise.
	 */
	excl = vtMemAllocZ(sizeof(Excl));
	excl->fsys = fid->fsys;
	excl->path = fid->qid.path;
	excl->time = t+LifeTime;
	if(ebox.tail != nil){
		excl->prev = ebox.tail;
		ebox.tail->next = excl;
	}
	else{
		ebox.head = excl;
		excl->prev = nil;
	}
	ebox.tail = excl;
	excl->next = nil;
	vtUnlock(ebox.lock);

	fid->excl = excl;
	return 1;
}
예제 #5
0
static File *
fileAlloc(Fs *fs)
{
	File *f;

	f = vtMemAllocZ(sizeof(File));
	f->lk = vtLockAlloc();
	f->ref = 1;
	f->fs = fs;
	f->boff = NilBlock;
	f->mode = fs->mode;
	return f;
}
예제 #6
0
static WThread*
getWThread(void)
{
	WThread *w;

	w = *wp;
	if(w == nil || w->pid != getpid()){
		w = vtMemAllocZ(sizeof(WThread));
		*wp = w;
		w->pid = getpid();
	}
	return w;
}
예제 #7
0
파일: 9srv.c 프로젝트: aahud/harvey
static Srv*
srvAlloc(char* service, int mode, int fd)
{
	Dir *dir;
	Srv *srv;
	int srvfd;
	char *mntpnt;

	vtLock(sbox.lock);
	for(srv = sbox.head; srv != nil; srv = srv->next){
		if(strcmp(srv->service, service) != 0)
			continue;
		/*
		 * If the service exists, but is stale,
		 * free it up and let the name be reused.
		 */
		if((dir = dirfstat(srv->srvfd)) != nil){
			free(dir);
			vtSetError("srv: already serving '%s'", service);
			vtUnlock(sbox.lock);
			return nil;
		}
		srvFree(srv);
		break;
	}

	if((srvfd = srvFd(service, mode, fd, &mntpnt)) < 0){
		vtUnlock(sbox.lock);
		return nil;
	}
	close(fd);

	srv = vtMemAllocZ(sizeof(Srv));
	srv->srvfd = srvfd;
	srv->service = vtStrDup(service);
	srv->mntpnt = mntpnt;

	if(sbox.tail != nil){
		srv->prev = sbox.tail;
		sbox.tail->next = srv;
	}
	else{
		sbox.head = srv;
		srv->prev = nil;
	}
	sbox.tail = srv;
	vtUnlock(sbox.lock);

	return srv;
}
예제 #8
0
파일: check.c 프로젝트: 99years/plan9
/*
 * Walk through all the blocks in the write buffer.
 * Then we can look for ones we missed -- those are leaks.
 */
static void
checkEpochs(Fsck *chk)
{
	u32int e;
	uint nb;

	nb = chk->nblocks;
	chk->amap = vtMemAllocZ(nb/8+1);
	chk->emap = vtMemAllocZ(nb/8+1);
	chk->xmap = vtMemAllocZ(nb/8+1);
	chk->errmap = vtMemAllocZ(nb/8+1);

	for(e = chk->fs->ehi; e >= chk->fs->elo; e--){
		memset(chk->emap, 0, chk->nblocks/8+1);
		memset(chk->xmap, 0, chk->nblocks/8+1);
		checkEpoch(chk, e);
	}
	checkLeak(chk);
	vtMemFree(chk->amap);
	vtMemFree(chk->emap);
	vtMemFree(chk->xmap);
	vtMemFree(chk->errmap);
}
예제 #9
0
파일: fs.c 프로젝트: bhanug/harvey
static Snap*
snapInit(Fs *fs)
{
	Snap *s;

	s = vtMemAllocZ(sizeof(Snap));
	s->fs = fs;
	s->tick = periodicAlloc(snapEvent, s, 10*1000);
	s->lk = vtLockAlloc();
	s->snapMinutes = -1;
	s->archMinute = -1;
	s->snapLife = -1;
	s->ignore = 5*2;	/* wait five minutes for clock to stabilize */
	return s;
}
예제 #10
0
파일: periodic.c 프로젝트: CoryXie/nix-os
Periodic *
periodicAlloc(void (*f)(void*), void *a, int msec)
{
	Periodic *p;

	p = vtMemAllocZ(sizeof(Periodic));
	p->lk = vtLockAlloc();
	p->f = f;
	p->a = a;
	p->msec = msec;
	if(p->msec < 10)
		p->msec = 10;

	vtThread(periodicThread, p);
	return p;
}
예제 #11
0
파일: 9lstn.c 프로젝트: 99years/plan9
static Lstn*
lstnAlloc(char* address, int flags)
{
	int afd;
	Lstn *lstn;
	char dir[NETPATHLEN];

	vtLock(lbox.lock);
	for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
		if(strcmp(lstn->address, address) != 0)
			continue;
		vtSetError("listen: already serving '%s'", address);
		vtUnlock(lbox.lock);
		return nil;
	}

	if((afd = announce(address, dir)) < 0){
		vtSetError("listen: announce '%s': %r", address);
		vtUnlock(lbox.lock);
		return nil;
	}

	lstn = vtMemAllocZ(sizeof(Lstn));
	lstn->afd = afd;
	lstn->address = vtStrDup(address);
	lstn->flags = flags;
	memmove(lstn->dir, dir, NETPATHLEN);

	if(lbox.tail != nil){
		lstn->prev = lbox.tail;
		lbox.tail->next = lstn;
	}
	else{
		lbox.head = lstn;
		lstn->prev = nil;
	}
	lbox.tail = lstn;
	vtUnlock(lbox.lock);

	if(vtThread(lstnListen, lstn) < 0){
		vtSetError("listen: thread '%s': %r", lstn->address);
		lstnFree(lstn);
		return nil;
	}

	return lstn;
}
예제 #12
0
파일: rpc.c 프로젝트: aahud/harvey
VtSession *
vtAlloc(void)
{
	VtSession *z;

	z = vtMemAllocZ(sizeof(VtSession));
	z->lk = vtLockAlloc();
//	z->inHash = vtSha1Alloc();
	z->inLock = vtLockAlloc();
	z->part = packetAlloc();
//	z->outHash = vtSha1Alloc();
	z->outLock = vtLockAlloc();
	z->fd = -1;
	z->uid = vtStrDup("anonymous");
	z->sid = vtStrDup("anonymous");
	return z;
}
예제 #13
0
static WEntry*
allocWEntry(void)
{
	int i;
	WEntry *w;

	w = pool;
	if(w == nil){
		w = vtMemAllocZ(1024*sizeof(WEntry));
		for(i=0; i<1024; i++)
			freeWEntry(&w[i]);
		w = pool;
	}
	pool = w->pnext;
	memset(w, 0, sizeof(WEntry));
	return w;
}
예제 #14
0
파일: archive.c 프로젝트: 99years/plan9
Arch *
archInit(Cache *c, Disk *disk, Fs *fs, VtSession *z)
{
	Arch *a;

	a = vtMemAllocZ(sizeof(Arch));

	a->c = c;
	a->z = z;
	a->fs = fs;
	a->blockSize = diskBlockSize(disk);
	a->lk = vtLockAlloc();
	a->starve = vtRendezAlloc(a->lk);

	a->ref = 2;
	vtThread(archThread, a);

	return a;
}
예제 #15
0
파일: check.c 프로젝트: 99years/plan9
void
fsCheck(Fsck *chk)
{
	Block *b;
	Super super;

	checkInit(chk);
	b = superGet(chk->cache, &super);
	if(b == nil){
		chk->print("could not load super block: %R");
		return;
	}
	blockPut(b);

	chk->hint = super.active;
	checkEpochs(chk);

	chk->smap = vtMemAllocZ(chk->nblocks/8+1);
	checkDirs(chk);
	vtMemFree(chk->smap);
}
예제 #16
0
파일: 9fid.c 프로젝트: 99years/plan9
static Fid*
fidAlloc(void)
{
	Fid *fid;

	vtLock(fbox.lock);
	if(fbox.nfree > 0){
		fid = fbox.free;
		fbox.free = fid->hash;
		fbox.nfree--;
	}
	else{
		fid = vtMemAllocZ(sizeof(Fid));
		fid->lock = vtLockAlloc();
		fid->alock = vtLockAlloc();
	}
	fbox.inuse++;
	vtUnlock(fbox.lock);

	fid->con = nil;
	fid->fidno = NOFID;
	fid->ref = 0;
	fid->flags = 0;
	fid->open = FidOCreate;
	assert(fid->fsys == nil);
	assert(fid->file == nil);
	fid->qid = (Qid){0, 0, 0};
	assert(fid->uid == nil);
	assert(fid->uname == nil);
	assert(fid->db == nil);
	assert(fid->excl == nil);
	assert(fid->rpc == nil);
	assert(fid->cuname == nil);
	fid->hash = fid->next = fid->prev = nil;

	return fid;
}
예제 #17
0
DirEntryEnum *
deeOpen(File *f)
{
	DirEntryEnum *dee;
	File *p;

	if(!fileIsDir(f)){
		vtSetError(ENotDir);
		fileDecRef(f);
		return nil;
	}

	/* flush out meta data */
	if(!fileLock(f))
		return nil;
	for(p=f->down; p; p=p->next)
		fileMetaFlush2(p, nil);
	fileUnlock(f);

	dee = vtMemAllocZ(sizeof(DirEntryEnum));
	dee->file = fileIncRef(f);

	return dee;
}
예제 #18
0
파일: plan9-io.c 프로젝트: npe9/harvey
void *
vtMemBrk(int n)
{
	static Lock lk;
	static uint8_t *buf;
	static int nbuf;
	static int nchunk;
	int align, pad;
	void *p;

	if(n >= IdealAlignment)
		align = IdealAlignment;
	else if(n > 8)
		align = 8;
	else	
		align = 4;

	lock(&lk);
	pad = (align - (uintptr)buf) & (align-1);
	if(n + pad > nbuf) {
		buf = vtMemAllocZ(ChunkSize);
		setmalloctag(buf, getcallerpc(&n));
		nbuf = ChunkSize;
		pad = (align - (uintptr)buf) & (align-1);
		nchunk++;
	}

	assert(n + pad <= nbuf);	
	
	p = buf + pad;
	buf += pad + n;
	nbuf -= pad + n;
	unlock(&lk);

	return p;
}
예제 #19
0
파일: fs.c 프로젝트: bhanug/harvey
Fs *
fsOpen(char *file, VtSession *z, int32_t ncache, int mode)
{
	int fd, m;
	uint8_t oscore[VtScoreSize];
	Block *b, *bs;
	Disk *disk;
	Fs *fs;
	Super super;

	switch(mode){
	default:
		vtSetError(EBadMode);
		return nil;
	case OReadOnly:
		m = OREAD;
		break;
	case OReadWrite:
		m = ORDWR;
		break;
	}
	fd = open(file, m);
	if(fd < 0){
		vtSetError("open %s: %r", file);
		return nil;
	}

	bwatchInit();
	disk = diskAlloc(fd);
	if(disk == nil){
		vtSetError("diskAlloc: %R");
		close(fd);
		return nil;
	}

	fs = vtMemAllocZ(sizeof(Fs));
	fs->mode = mode;
	fs->name = vtStrDup(file);
	fs->blockSize = diskBlockSize(disk);
	fs->elk = vtLockAlloc();
	fs->cache = cacheAlloc(disk, z, ncache, mode);
	if(mode == OReadWrite && z)
		fs->arch = archInit(fs->cache, disk, fs, z);
	fs->z = z;

	b = cacheLocal(fs->cache, PartSuper, 0, mode);
	if(b == nil)
		goto Err;
	if(!superUnpack(&super, b->data)){
		blockPut(b);
		vtSetError("bad super block");
		goto Err;
	}
	blockPut(b);

	fs->ehi = super.epochHigh;
	fs->elo = super.epochLow;

//fprint(2, "%s: fs->ehi %d fs->elo %d active=%d\n", argv0, fs->ehi, fs->elo, super.active);

	fs->source = sourceRoot(fs, super.active, mode);
	if(fs->source == nil){
		/*
		 * Perhaps it failed because the block is copy-on-write.
		 * Do the copy and try again.
		 */
		if(mode == OReadOnly || strcmp(vtGetError(), EBadRoot) != 0)
			goto Err;
		b = cacheLocalData(fs->cache, super.active, BtDir, RootTag,
			OReadWrite, 0);
		if(b == nil){
			vtSetError("cacheLocalData: %R");
			goto Err;
		}
		if(b->l.epoch == fs->ehi){
			blockPut(b);
			vtSetError("bad root source block");
			goto Err;
		}
		b = blockCopy(b, RootTag, fs->ehi, fs->elo);
		if(b == nil)
			goto Err;
		localToGlobal(super.active, oscore);
		super.active = b->addr;
		bs = cacheLocal(fs->cache, PartSuper, 0, OReadWrite);
		if(bs == nil){
			blockPut(b);
			vtSetError("cacheLocal: %R");
			goto Err;
		}
		superPack(&super, bs->data);
		blockDependency(bs, b, 0, oscore, nil);
		blockPut(b);
		blockDirty(bs);
		blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0);
		blockPut(bs);
		fs->source = sourceRoot(fs, super.active, mode);
		if(fs->source == nil){
			vtSetError("sourceRoot: %R");
			goto Err;
		}
	}

//fprint(2, "%s: got fs source\n", argv0);

	vtRLock(fs->elk);
	fs->file = fileRoot(fs->source);
	fs->source->file = fs->file;		/* point back */
	vtRUnlock(fs->elk);
	if(fs->file == nil){
		vtSetError("fileRoot: %R");
		goto Err;
	}

//fprint(2, "%s: got file root\n", argv0);

	if(mode == OReadWrite){
		fs->metaFlush = periodicAlloc(fsMetaFlush, fs, 1000);
		fs->snap = snapInit(fs);
	}
	return fs;

Err:
fprint(2, "%s: fsOpen error\n", argv0);
	fsClose(fs);
	return nil;
}
예제 #20
0
파일: source.c 프로젝트: npe9/harvey
static Source *
sourceAlloc(Fs *fs, Block *b, Source *p, uint32_t offset, int mode,
            int issnapshot)
{
    int epb;
    uint32_t epoch;
    char *pname = nil;
    Source *r;
    Entry e;

    assert(p==nil || sourceIsLocked(p));

    if(p == nil) {
        assert(offset == 0);
        epb = 1;
    } else
        epb = p->dsize / VtEntrySize;

    if(b->l.type != BtDir)
        goto Bad;

    /*
     * a non-active entry is the only thing that
     * can legitimately happen here. all the others
     * get prints.
     */
    if(!entryUnpack(&e, b->data, offset % epb)) {
        pname = sourceName(p);
        consPrint("%s: %s %V: sourceAlloc: entryUnpack failed\n",
                  fs->name, pname, b->score);
        goto Bad;
    }
    if(!(e.flags & VtEntryActive)) {
        pname = sourceName(p);
        if(0) consPrint("%s: %s %V: sourceAlloc: not active\n",
                            fs->name, pname, e.score);
        goto Bad;
    }
    if(e.psize < 256 || e.dsize < 256) {
        pname = sourceName(p);
        consPrint("%s: %s %V: sourceAlloc: psize %ud or dsize %ud < 256\n",
                  fs->name, pname, e.score, e.psize, e.dsize);
        goto Bad;
    }

    if(e.depth < sizeToDepth(e.size, e.psize, e.dsize)) {
        pname = sourceName(p);
        consPrint("%s: %s %V: sourceAlloc: depth %ud size %llud "
                  "psize %ud dsize %ud\n", fs->name, pname,
                  e.score, e.depth, e.size, e.psize, e.dsize);
        goto Bad;
    }

    if((e.flags & VtEntryLocal) && e.tag == 0) {
        pname = sourceName(p);
        consPrint("%s: %s %V: sourceAlloc: flags %#ux tag %#ux\n",
                  fs->name, pname, e.score, e.flags, e.tag);
        goto Bad;
    }

    if(e.dsize > fs->blockSize || e.psize > fs->blockSize) {
        pname = sourceName(p);
        consPrint("%s: %s %V: sourceAlloc: psize %ud or dsize %ud "
                  "> blocksize %ud\n", fs->name, pname, e.score,
                  e.psize, e.dsize, fs->blockSize);
        goto Bad;
    }

    epoch = b->l.epoch;
    if(mode == OReadWrite) {
        if(e.snap != 0) {
            vtSetError(ESnapRO);
            return nil;
        }
    } else if(e.snap != 0) {
        if(e.snap < fs->elo) {
            vtSetError(ESnapOld);
            return nil;
        }
        if(e.snap >= fs->ehi)
            goto Bad;
        epoch = e.snap;
    }

    r = vtMemAllocZ(sizeof(Source));
    r->fs = fs;
    r->mode = mode;
    r->issnapshot = issnapshot;
    r->dsize = e.dsize;
    r->gen = e.gen;
    r->dir = (e.flags & VtEntryDir) != 0;
    r->lk = vtLockAlloc();
    r->ref = 1;
    r->parent = p;
    if(p) {
        vtLock(p->lk);
        assert(mode == OReadOnly || p->mode == OReadWrite);
        p->ref++;
        vtUnlock(p->lk);
    }
    r->epoch = epoch;
//	consPrint("sourceAlloc: have %V be.%d fse.%d %s\n", b->score,
//		b->l.epoch, r->fs->ehi, mode == OReadWrite? "rw": "ro");
    memmove(r->score, b->score, VtScoreSize);
    r->scoreEpoch = b->l.epoch;
    r->offset = offset;
    r->epb = epb;
    r->tag = b->l.tag;

//	consPrint("%s: sourceAlloc: %p -> %V %d\n", r, r->score, r->offset);

    return r;
Bad:
    free(pname);
    vtSetError(EBadEntry);
    return nil;
}
예제 #21
0
파일: 9user.c 프로젝트: 99years/plan9
static int
uboxInit(char* users, int len)
{
	User *g, *u;
	Ubox *box, *obox;
	int blank, comment, i, nline, nuser;
	char *buf, *f[5], **line, *p, *q, *s;

	/*
	 * Strip out whitespace and comments.
	 * Note that comments are pointless, they disappear
	 * when the server writes the database back out.
	 */
	blank = 1;
	comment = nline = 0;

	s = p = buf = vtMemAlloc(len+1);
	for(q = users; *q != '\0'; q++){
		if(*q == '\r' || *q == '\t' || *q == ' ')
			continue;
		if(*q == '\n'){
			if(!blank){
				if(p != s){
					*p++ = '\n';
					nline++;
					s = p;
				}
				blank = 1;
			}
			comment = 0;
			continue;
		}
		if(*q == '#')
			comment = 1;
		blank = 0;
		if(!comment)
			*p++ = *q;
	}
	*p = '\0';

	line = vtMemAllocZ((nline+2)*sizeof(char*));
	if((i = gettokens(buf, line, nline+2, "\n")) != nline){
		fprint(2, "nline %d (%d) botch\n", nline, i);
		vtMemFree(line);
		vtMemFree(buf);
		return 0;
	}

	/*
	 * Everything is updated in a local Ubox until verified.
	 */
	box = vtMemAllocZ(sizeof(Ubox));

	/*
	 * First pass - check format, check for duplicates
	 * and enter in hash buckets.
	 */
	nuser = 0;
	for(i = 0; i < nline; i++){
		s = vtStrDup(line[i]);
		if(getfields(s, f, nelem(f), 0, ":") != 4){
			fprint(2, "bad line '%s'\n", line[i]);
			vtMemFree(s);
			continue;
		}
		if(*f[0] == '\0' || *f[1] == '\0'){
			fprint(2, "bad line '%s'\n", line[i]);
			vtMemFree(s);
			continue;
		}
		if(!validUserName(f[0])){
			fprint(2, "invalid uid '%s'\n", f[0]);
			vtMemFree(s);
			continue;
		}
		if(_userByUid(box, f[0]) != nil){
			fprint(2, "duplicate uid '%s'\n", f[0]);
			vtMemFree(s);
			continue;
		}
		if(!validUserName(f[1])){
			fprint(2, "invalid uname '%s'\n", f[0]);
			vtMemFree(s);
			continue;
		}
		if(_userByUname(box, f[1]) != nil){
			fprint(2, "duplicate uname '%s'\n", f[1]);
			vtMemFree(s);
			continue;
		}

		u = userAlloc(f[0], f[1]);
		uboxAddUser(box, u);
		line[nuser] = line[i];
		nuser++;

		vtMemFree(s);
	}
	assert(box->nuser == nuser);

	/*
	 * Second pass - fill in leader and group information.
	 */
	for(i = 0; i < nuser; i++){
		s = vtStrDup(line[i]);
		getfields(s, f, nelem(f), 0, ":");

		assert(g = _userByUname(box, f[1]));
		if(*f[2] != '\0'){
			if((u = _userByUname(box, f[2])) == nil)
				g->leader = vtStrDup(g->uname);
			else
				g->leader = vtStrDup(u->uname);
			box->len += strlen(g->leader);
		}
		for(p = f[3]; p != nil; p = q){
			if((q = utfrune(p, L',')) != nil)
				*q++ = '\0';
			if(!_groupAddMember(box, g, p)){
				// print/log error here
			}
		}

		vtMemFree(s);
	}

	vtMemFree(line);
	vtMemFree(buf);

	for(i = 0; usersMandatory[i] != nil; i++){
		if((u = _userByUid(box, usersMandatory[i])) == nil){
			vtSetError("user '%s' is mandatory", usersMandatory[i]);
			uboxFree(box);
			return 0;
		}
		if(strcmp(u->uid, u->uname) != 0){
			vtSetError("uid/uname for user '%s' must match",
				usersMandatory[i]);
			uboxFree(box);
			return 0;
		}
	}

	vtLock(ubox.lock);
	obox = ubox.box;
	ubox.box = box;
	vtUnlock(ubox.lock);

	if(obox != nil)
		uboxFree(obox);

	return 1;
}
예제 #22
0
void
main(int argc, char *argv[])
{
	int fd, force;
	Header h;
	ulong bn;
	Entry e;
	char *label = "vfs";
	char *host = nil;
	char *score = nil;
	u32int root;
	Dir *d;

	force = 0;
	ARGBEGIN{
	default:
		usage();
	case 'b':
		bsize = unittoull(EARGF(usage()));
		if(bsize == ~0)
			usage();
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 'i':
		iso9660file = EARGF(usage());
		iso9660off = atoi(EARGF(usage()));
		break;
	case 'l':
		label = EARGF(usage());
		break;
	case 'v':
		score = EARGF(usage());
		break;

	/*
	 * This is -y instead of -f because flchk has a
	 * (frequently used) -f option.  I type flfmt instead
	 * of flchk all the time, and want to make it hard
	 * to reformat my file system accidentally.
	 */
	case 'y':
		force = 1;
		break;
	}ARGEND

	if(argc != 1)
		usage();

	if(iso9660file && score)
		vtFatal("cannot use -i with -v");

	vtAttach();

	fmtinstall('V', scoreFmt);
	fmtinstall('R', vtErrFmt);
	fmtinstall('L', labelFmt);

	fd = open(argv[0], ORDWR);
	if(fd < 0)
		vtFatal("could not open file: %s: %r", argv[0]);

	buf = vtMemAllocZ(bsize);
	if(pread(fd, buf, bsize, HeaderOffset) != bsize)
		vtFatal("could not read fs header block: %r");

	if(headerUnpack(&h, buf) && !force
	&& !confirm("fs header block already exists; are you sure?"))
		goto Out;

	if((d = dirfstat(fd)) == nil)
		vtFatal("dirfstat: %r");

	if(d->type == 'M' && !force
	&& !confirm("fs file is mounted via devmnt (is not a kernel device); are you sure?"))
		goto Out;

	partition(fd, bsize, &h);
	headerPack(&h, buf);
	if(pwrite(fd, buf, bsize, HeaderOffset) < bsize)
		vtFatal("could not write fs header: %r");

	disk = diskAlloc(fd);
	if(disk == nil)
		vtFatal("could not open disk: %r");

	if(iso9660file)
		iso9660init(fd, &h, iso9660file, iso9660off);

	/* zero labels */
	memset(buf, 0, bsize);
	for(bn = 0; bn < diskSize(disk, PartLabel); bn++)
		blockWrite(PartLabel, bn);

	if(iso9660file)
		iso9660labels(disk, buf, blockWrite);

	if(score)
		root = ventiRoot(host, score);
	else{
		rootMetaInit(&e);
		root = rootInit(&e);
	}

	superInit(label, root, vtZeroScore);
	diskFree(disk);

	if(score == nil)
		topLevel(argv[0]);

Out:
	vtDetach();
	exits(0);
}
예제 #23
0
파일: plan9-thread.c 프로젝트: npe9/harvey
VtLock*
vtLockAlloc(void)
{
	return vtMemAllocZ(sizeof(VtLock));
}
예제 #24
0
파일: check.c 프로젝트: 99years/plan9
/*
 * Walk the source tree making sure that the BtData
 * sources containing directory entries are okay.
 */
static void
chkDir(Fsck *chk, char *name, Source *source, Source *meta)
{
	int i;
	u32int a1, a2, nb, o;
	char *s, *nn;
	uchar *bm;
	Block *b, *bb;
	DirEntry de;
	Entry e1, e2;
	MetaBlock mb;
	MetaEntry me;
	Source *r, *mr;

	if(!chk->useventi && globalToLocal(source->score)==NilBlock &&
	    globalToLocal(meta->score)==NilBlock)
		return;

	if(!sourceLock2(source, meta, OReadOnly)){
		warn(chk, "could not lock sources for %s: %R", name);
		return;
	}
	if(!sourceGetEntry(source, &e1) || !sourceGetEntry(meta, &e2)){
		warn(chk, "could not load entries for %s: %R", name);
		return;
	}
	a1 = globalToLocal(e1.score);
	a2 = globalToLocal(e2.score);
	if((!chk->useventi && a1==NilBlock && a2==NilBlock)
	|| (getBit(chk->smap, a1) && getBit(chk->smap, a2))){
		sourceUnlock(source);
		sourceUnlock(meta);
		return;
	}
	setBit(chk->smap, a1);
	setBit(chk->smap, a2);

	bm = vtMemAllocZ(sourceGetDirSize(source)/8 + 1);

	nb = (sourceGetSize(meta) + meta->dsize - 1)/meta->dsize;
	for(o = 0; o < nb; o++){
		b = sourceBlock(meta, o, OReadOnly);
		if(b == nil){
			error(chk, "could not read block in meta file: %s[%ud]: %R",
				name, o);
			continue;
		}
if(0)		fprint(2, "source %V:%d block %d addr %d\n", source->score,
			source->offset, o, b->addr);
		if(b->addr != NilBlock && getBit(chk->errmap, b->addr))
			warn(chk, "previously reported error in block %ux is in %s",
				b->addr, name);

		if(!mbUnpack(&mb, b->data, meta->dsize)){
			error(chk, "could not unpack meta block: %s[%ud]: %R",
				name, o);
			blockPut(b);
			continue;
		}
		if(!chkMetaBlock(&mb)){
			error(chk, "bad meta block: %s[%ud]: %R", name, o);
			blockPut(b);
			continue;
		}
		s = nil;
		for(i=mb.nindex-1; i>=0; i--){
			meUnpack(&me, &mb, i);
			if(!deUnpack(&de, &me)){
				error(chk,
				  "could not unpack dir entry: %s[%ud][%d]: %R",
					name, o, i);
				continue;
			}
			if(s && strcmp(s, de.elem) <= 0)
				error(chk,
			   "dir entry out of order: %s[%ud][%d] = %s last = %s",
					name, o, i, de.elem, s);
			vtMemFree(s);
			s = vtStrDup(de.elem);
			nn = smprint("%s/%s", name, de.elem);
			if(nn == nil){
				error(chk, "out of memory");
				continue;
			}
			if(chk->printdirs)
				if(de.mode&ModeDir)
					chk->print("%s/\n", nn);
			if(chk->printfiles)
				if(!(de.mode&ModeDir))
					chk->print("%s\n", nn);
			if(!(de.mode & ModeDir)){
				r = openSource(chk, source, nn, bm, de.entry,
					de.gen, 0, &mb, i, b);
				if(r != nil){
					if(sourceLock(r, OReadOnly)){
						scanSource(chk, nn, r);
						sourceUnlock(r);
					}
					sourceClose(r);
				}
				deCleanup(&de);
				free(nn);
				continue;
			}

			r = openSource(chk, source, nn, bm, de.entry,
				de.gen, 1, &mb, i, b);
			if(r == nil){
				deCleanup(&de);
				free(nn);
				continue;
			}

			mr = openSource(chk, source, nn, bm, de.mentry,
				de.mgen, 0, &mb, i, b);
			if(mr == nil){
				sourceClose(r);
				deCleanup(&de);
				free(nn);
				continue;
			}

			if(!(de.mode&ModeSnapshot) || chk->walksnapshots)
				chkDir(chk, nn, r, mr);

			sourceClose(mr);
			sourceClose(r);
			deCleanup(&de);
			free(nn);
			deCleanup(&de);

		}
		vtMemFree(s);
		blockPut(b);
	}

	nb = sourceGetDirSize(source);
	for(o=0; o<nb; o++){
		if(getBit(bm, o))
			continue;
		r = sourceOpen(source, o, OReadOnly, 0);
		if(r == nil)
			continue;
		warn(chk, "non referenced entry in source %s[%d]", name, o);
		if((bb = sourceBlock(source, o/(source->dsize/VtEntrySize),
		    OReadOnly)) != nil){
			if(bb->addr != NilBlock){
				setBit(chk->errmap, bb->addr);
				chk->clre(chk, bb, o%(source->dsize/VtEntrySize));
				chk->nclre++;
			}
			blockPut(bb);
		}
		sourceClose(r);
	}

	sourceUnlock(source);
	sourceUnlock(meta);
	vtMemFree(bm);
}