Пример #1
0
static void
uboxDump(Ubox* box)
{
	User* u;

	consPrint("nuser %d len = %d\n", box->nuser, box->len);

	for(u = box->head; u != nil; u = u->next)
		consPrint("%U\n", u);
}
Пример #2
0
static Source *
fileOpenSource(File *f, u32int offset, u32int gen, int dir, uint mode,
	int issnapshot)
{
	char *rname, *fname;
	Source *r;

	if(!sourceLock(f->source, mode))
		return nil;
	r = sourceOpen(f->source, offset, mode, issnapshot);
	sourceUnlock(f->source);
	if(r == nil)
		return nil;
	if(r->gen != gen){
		vtSetError(ERemoved);
		goto Err;
	}
	if(r->dir != dir && r->mode != -1){
		/* this hasn't been as useful as we hoped it would be. */
		rname = sourceName(r);
		fname = fileName(f);
		consPrint("%s: source %s for file %s: fileOpenSource: "
			"dir mismatch %d %d\n",
			f->source->fs->name, rname, fname, r->dir, dir);
		free(rname);
		free(fname);

		vtSetError(EBadMeta);
		goto Err;
	}
	return r;
Err:
	sourceClose(r);
	return nil;
}
Пример #3
0
static int
cmdLstn(int argc, char* argv[])
{
	int dflag, flags;
	Lstn *lstn;
	char *usage = "usage: listen [-dIN] [address]";

	dflag = 0;
	flags = 0;
	ARGBEGIN{
	default:
		return cliError(usage);
	case 'd':
		dflag = 1;
		break;
	case 'I':
		flags |= ConIPCheck;
		break;
	case 'N':
		flags |= ConNoneAllow;
		break;
	}ARGEND

	switch(argc){
	default:
		return cliError(usage);
	case 0:
		vtRLock(lbox.lock);
		for(lstn = lbox.head; lstn != nil; lstn = lstn->next)
			consPrint("\t%s\t%s\n", lstn->address, lstn->dir);
		vtRUnlock(lbox.lock);
		break;
	case 1:
		if(!dflag){
			if(lstnAlloc(argv[0], flags) == nil)
				return 0;
			break;
		}

		vtLock(lbox.lock);
		for(lstn = lbox.head; lstn != nil; lstn = lstn->next){
			if(strcmp(lstn->address, argv[0]) != 0)
				continue;
			if(lstn->afd != -1){
				close(lstn->afd);
				lstn->afd = -1;
			}
			break;
		}
		vtUnlock(lbox.lock);

		if(lstn == nil){
			vtSetError("listen: '%s' not found", argv[0]);
			return 0;
		}
		break;
	}

	return 1;
}
Пример #4
0
static int
cmdUsers(int argc, char* argv[])
{
	Ubox *box;
	int dflag, r, wflag;
	char *file;
	char *usage = "usage: users [-d | -r file] [-w]";

	dflag = wflag = 0;
	file = nil;

	ARGBEGIN{
	default:
		return cliError(usage);
	case 'd':
		dflag = 1;
		break;
	case 'r':
		file = ARGF();
		if(file == nil)
			return cliError(usage);
		break;
	case 'w':
		wflag = 1;
		break;
	}ARGEND

	if(argc)
		return cliError(usage);

	if(dflag && file)
		return cliError("cannot use -d and -r together");

	if(dflag)
		uboxInit(usersDefault, sizeof(usersDefault));
	else if(file){
		if(usersFileRead(file) == 0)
			return 0;
	}

	vtRLock(ubox.lock);
	box = ubox.box;
	consPrint("\tnuser %d len %d\n", box->nuser, box->len);

	r = 1;
	if(wflag)
		r = usersFileWrite(box);
	vtRUnlock(ubox.lock);
	return r;
}
Пример #5
0
Source *
sourceRoot(Fs *fs, uint32_t addr, int mode)
{
    Source *r;
    Block *b;

    b = cacheLocalData(fs->cache, addr, BtDir, RootTag, mode, 0);
    if(b == nil)
        return nil;

    if(mode == OReadWrite && b->l.epoch != fs->ehi) {
        consPrint("sourceRoot: fs->ehi = %ud, b->l = %L\n",
                  fs->ehi, &b->l);
        blockPut(b);
        vtSetError(EBadRoot);
        return nil;
    }

    r = sourceAlloc(fs, b, nil, 0, mode, 0);
    blockPut(b);
    return r;
}
Пример #6
0
static int
cmdUname(int argc, char* argv[])
{
	User *u, *up;
	int d, dflag, i, r;
	char *p, *uid, *uname;
	char *createfmt = "fsys main create /active/usr/%s %s %s d775";
	char *usage = "usage: uname [-d] uname [uid|:uid|%%newname|=leader|+member|-member]";

	dflag = 0;

	ARGBEGIN{
	default:
		return cliError(usage);
	case 'd':
		dflag = 1;
		break;
	}ARGEND

	if(argc < 1){
		if(!dflag)
			return cliError(usage);
		vtRLock(ubox.lock);
		uboxDump(ubox.box);
		vtRUnlock(ubox.lock);
		return 1;
	}

	uname = argv[0];
	argc--; argv++;

	if(argc == 0){
		vtRLock(ubox.lock);
		if((u = _userByUname(ubox.box, uname)) == nil){
			vtRUnlock(ubox.lock);
			return 0;
		}
		consPrint("\t%U\n", u);
		vtRUnlock(ubox.lock);
		return 1;
	}

	vtLock(ubox.lock);
	u = _userByUname(ubox.box, uname);
	while(argc--){
		if(argv[0][0] == '%'){
			if(u == nil){
				vtUnlock(ubox.lock);
				return 0;
			}
			p = &argv[0][1];
			if((up = _userByUname(ubox.box, p)) != nil){
				vtSetError("uname: uname '%s' already exists",
					up->uname);
				vtUnlock(ubox.lock);
				return 0;
			}
			for(i = 0; usersMandatory[i] != nil; i++){
				if(strcmp(usersMandatory[i], uname) != 0)
					continue;
				vtSetError("uname: uname '%s' is mandatory",
					uname);
				vtUnlock(ubox.lock);
				return 0;
			}

			d = strlen(p) - strlen(u->uname);
			for(up = ubox.box->head; up != nil; up = up->next){
				if(up->leader != nil){
					if(strcmp(up->leader, u->uname) == 0){
						vtMemFree(up->leader);
						up->leader = vtStrDup(p);
						ubox.box->len += d;
					}
				}
				for(i = 0; i < up->ngroup; i++){
					if(strcmp(up->group[i], u->uname) != 0)
						continue;
					vtMemFree(up->group[i]);
					up->group[i] = vtStrDup(p);
					ubox.box->len += d;
					break;
				}
			}

			uboxRemUser(ubox.box, u);
			vtMemFree(u->uname);
			u->uname = vtStrDup(p);
			uboxAddUser(ubox.box, u);
		}
		else if(argv[0][0] == '='){
			if(u == nil){
				vtUnlock(ubox.lock);
				return 0;
			}
			if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
				if(argv[0][1] != '\0'){
					vtUnlock(ubox.lock);
					return 0;
				}
			}
			if(u->leader != nil){
				ubox.box->len -= strlen(u->leader);
				vtMemFree(u->leader);
				u->leader = nil;
			}
			if(up != nil){
				u->leader = vtStrDup(up->uname);
				ubox.box->len += strlen(u->leader);
			}
		}
		else if(argv[0][0] == '+'){
			if(u == nil){
				vtUnlock(ubox.lock);
				return 0;
			}
			if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
				vtUnlock(ubox.lock);
				return 0;
			}
			if(!_groupAddMember(ubox.box, u, up->uname)){
				vtUnlock(ubox.lock);
				return 0;
			}
		}
		else if(argv[0][0] == '-'){
			if(u == nil){
				vtUnlock(ubox.lock);
				return 0;
			}
			if((up = _userByUname(ubox.box, &argv[0][1])) == nil){
				vtUnlock(ubox.lock);
				return 0;
			}
			if(!_groupRemMember(ubox.box, u, up->uname)){
				vtUnlock(ubox.lock);
				return 0;
			}
		}
		else{
			if(u != nil){
				vtSetError("uname: uname '%s' already exists",
					u->uname);
				vtUnlock(ubox.lock);
				return 0;
			}

			uid = argv[0];
			if(*uid == ':')
				uid++;
			if((u = _userByUid(ubox.box, uid)) != nil){
				vtSetError("uname: uid '%s' already exists",
					u->uid);
				vtUnlock(ubox.lock);
				return 0;
			}

			u = userAlloc(uid, uname);
			uboxAddUser(ubox.box, u);
			if(argv[0][0] != ':'){
				// should have an option for the mode and gid
				p = smprint(createfmt, uname, uname, uname);
				r = cliExec(p);
				vtMemFree(p);
				if(r == 0){
					vtUnlock(ubox.lock);
					return 0;
				}
			}
		}
		argv++;
	}

	if(usersFileWrite(ubox.box) == 0){
		vtUnlock(ubox.lock);
		return 0;
	}
	if(dflag)
		uboxDump(ubox.box);
	vtUnlock(ubox.lock);

	return 1;
}
Пример #7
0
static int
cmdSrv(int argc, char* argv[])
{
	Con *con;
	Srv *srv;
	char *usage = "usage: srv [-APWdp] [service]";
	int conflags, dflag, fd[2], mode, pflag, r;

	dflag = 0;
	pflag = 0;
	conflags = 0;
	mode = 0666;

	ARGBEGIN{
	default:
		return cliError(usage);
	case 'A':
		conflags |= ConNoAuthCheck;
		break;
	case 'I':
		conflags |= ConIPCheck;
		break;
	case 'N':
		conflags |= ConNoneAllow;
		break;
	case 'P':
		conflags |= ConNoPermCheck;
		mode = 0600;
		break;
	case 'W':
		conflags |= ConWstatAllow;
		mode = 0600;
		break;
	case 'd':
		dflag = 1;
		break;
	case 'p':
		pflag = 1;
		mode = 0600;
		break;
	}ARGEND

	if(pflag && (conflags&ConNoPermCheck)){
		vtSetError("srv: cannot use -P with -p");
		return 0;
	}

	switch(argc){
	default:
		return cliError(usage);
	case 0:
		vtRLock(sbox.lock);
		for(srv = sbox.head; srv != nil; srv = srv->next)
			consPrint("\t%s\t%d\n", srv->service, srv->srvfd);
		vtRUnlock(sbox.lock);

		return 1;
	case 1:
		if(!dflag)
			break;

		vtLock(sbox.lock);
		for(srv = sbox.head; srv != nil; srv = srv->next){
			if(strcmp(srv->service, argv[0]) != 0)
				continue;
			srvFree(srv);
			break;
		}
		vtUnlock(sbox.lock);

		if(srv == nil){
			vtSetError("srv: '%s' not found", argv[0]);
			return 0;
		}

		return 1;
	}

	if(pipe(fd) < 0){
		vtSetError("srv pipe: %r");
		return 0;
	}
	if((srv = srvAlloc(argv[0], mode, fd[0])) == nil){
		close(fd[0]); close(fd[1]);
		return 0;
	}

	if(pflag)
		r = consOpen(fd[1], srv->srvfd, -1);
	else{
		con = conAlloc(fd[1], srv->mntpnt, conflags);
		if(con == nil)
			r = 0;
		else
			r = 1;
	}
	if(r == 0){
		close(fd[1]);
		vtLock(sbox.lock);
		srvFree(srv);
		vtUnlock(sbox.lock);
	}

	return r;
}
Пример #8
0
void
main(int argc, char* argv[])
{
	char **cmd, *p;
	int i, ncmd, tflag;

	fmtinstall('D', dirfmt);
	fmtinstall('F', fcallfmt);
	fmtinstall('M', dirmodefmt);
	quotefmtinstall();

	/*
	 * Insulate from the invoker's environment.
	 */
	if(rfork(RFREND|RFNOTEG|RFNAMEG) < 0)
		sysfatal("rfork: %r");

	close(0);
	open("/dev/null", OREAD);
	close(1);
	open("/dev/null", OWRITE);

	cmd = nil;
	ncmd = tflag = 0;

	vtAttach();

	ARGBEGIN{
	case '?':
	default:
		usage();
		break;
	case 'c':
		p = EARGF(usage());
		currfsysname = p;
		cmd = vtMemRealloc(cmd, (ncmd+1)*sizeof(char*));
		cmd[ncmd++] = p;
		break;
	case 'D':
		Dflag ^= 1;
		break;
	case 'f':
		p = EARGF(usage());
		currfsysname = foptname = p;
		readCmdPart(p, &cmd, &ncmd);
		break;
	case 'm':
		mempcnt = atoi(EARGF(usage()));
		if(mempcnt <= 0 || mempcnt >= 100)
			usage();
		break;
	case 't':
		tflag = 1;
		break;
	}ARGEND
	if(argc != 0)
		usage();

	consInit();
	cliInit();
	msgInit();
	conInit();
	cmdInit();
	fsysInit();
	exclInit();
	fidInit();

	srvInit();
	lstnInit();
	usersInit();

	for(i = 0; i < ncmd; i++)
		if(cliExec(cmd[i]) == 0)
			fprint(2, "%s: %R\n", cmd[i]);
	vtMemFree(cmd);

	if(tflag && consTTY() == 0)
		consPrint("%s\n", vtGetError());

	vtDetach();
	exits(0);
}
Пример #9
0
static void
archThread(void *v)
{
	Arch *a = v;
	Block *b;
	Param p;
	Super super;
	int ret;
	u32int addr;
	uchar rbuf[VtRootSize];
	VtRoot root;

	vtThreadSetName("arch");

	for(;;){
		/* look for work */
		vtLock(a->fs->elk);
		b = superGet(a->c, &super);
		if(b == nil){
			vtUnlock(a->fs->elk);
			fprint(2, "archThread: superGet: %R\n");
			sleep(60*1000);
			continue;
		}
		addr = super.next;
		if(addr != NilBlock && super.current == NilBlock){
			super.current = addr;
			super.next = NilBlock;
			superPack(&super, b->data);
			blockDirty(b);
		}else
			addr = super.current;
		blockPut(b);
		vtUnlock(a->fs->elk);

		if(addr == NilBlock){
			/* wait for work */
			vtLock(a->lk);
			vtSleep(a->starve);
			if(a->die != nil)
				goto Done;
			vtUnlock(a->lk);
			continue;
		}

sleep(10*1000);	/* window of opportunity to provoke races */

		/* do work */
		memset(&p, 0, sizeof p);
		p.blockSize = a->blockSize;
		p.dsize = 3*VtEntrySize;	/* root has three Entries */
		p.c = a->c;
		p.a = a;

		ret = archWalk(&p, addr, BtDir, RootTag);
		switch(ret){
		default:
			abort();
		case ArchFailure:
			fprint(2, "archiveBlock %#ux: %R\n", addr);
			sleep(60*1000);
			continue;
		case ArchSuccess:
		case ArchFaked:
			break;
		}

		if(0) fprint(2, "archiveSnapshot 0x%#ux: maxdepth %ud nfixed %ud"
			" send %ud nfailsend %ud nvisit %ud"
			" nreclaim %ud nfake %ud nreal %ud\n",
			addr, p.maxdepth, p.nfixed,
			p.nsend, p.nfailsend, p.nvisit,
			p.nreclaim, p.nfake, p.nreal);
		if(0) fprint(2, "archiveBlock %V (%ud)\n", p.score, p.blockSize);

		/* tie up vac root */
		memset(&root, 0, sizeof root);
		root.version = VtRootVersion;
		strecpy(root.type, root.type+sizeof root.type, "vac");
		strecpy(root.name, root.name+sizeof root.name, "fossil");
		memmove(root.score, p.score, VtScoreSize);
		memmove(root.prev, super.last, VtScoreSize);
		root.blockSize = a->blockSize;
		vtRootPack(&root, rbuf);
		if(!vtWrite(a->z, p.score, VtRootType, rbuf, VtRootSize)
		|| !vtSha1Check(p.score, rbuf, VtRootSize)){
			fprint(2, "vtWriteBlock %#ux: %R\n", addr);
			sleep(60*1000);
			continue;
		}

		/* record success */
		vtLock(a->fs->elk);
		b = superGet(a->c, &super);
		if(b == nil){
			vtUnlock(a->fs->elk);
			fprint(2, "archThread: superGet: %R\n");
			sleep(60*1000);
			continue;
		}
		super.current = NilBlock;
		memmove(super.last, p.score, VtScoreSize);
		superPack(&super, b->data);
		blockDirty(b);
		blockPut(b);
		vtUnlock(a->fs->elk);

		consPrint("archive vac:%V\n", p.score);
	}

Done:
	a->ref--;
	vtWakeup(a->die);
	vtUnlock(a->lk);
}
Пример #10
0
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;
}
Пример #11
0
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;
}