예제 #1
0
파일: fs.c 프로젝트: bhanug/harvey
void
fsSnapshotRemove(Fs *fs)
{
	vtRLock(fs->elk);
	fsRsearch(fs, "/snapshot");
	vtRUnlock(fs->elk);
}
예제 #2
0
파일: 9fid.c 프로젝트: 99years/plan9
static void
fidLock(Fid* fid, int flags)
{
	if(flags & FidFWlock){
		vtLock(fid->lock);
		fid->flags = flags;
	}
	else
		vtRLock(fid->lock);

	/*
	 * Callers of file* routines are expected to lock fsys->fs->elk
	 * before making any calls in order to make sure the epoch doesn't
	 * change underfoot. With the exception of Tversion and Tattach,
	 * that implies all 9P functions need to lock on entry and unlock
	 * on exit. Fortunately, the general case is the 9P functions do
	 * fidGet on entry and fidPut on exit, so this is a convenient place
	 * to do the locking.
	 * No fsys->fs->elk lock is required if the fid is being created
	 * (Tauth, Tattach and Twalk). FidFCreate is always accompanied by
	 * FidFWlock so the setting and testing of FidFCreate here and in
	 * fidUnlock below is always done under fid->lock.
	 * A side effect is that fidFree is called with the fid locked, and
	 * must call fidUnlock only after it has disposed of any File
	 * resources still held.
	 */
	if(!(flags & FidFCreate))
		fsysFsRlock(fid->fsys);
}
예제 #3
0
파일: 9user.c 프로젝트: 99years/plan9
int
groupWriteMember(char* uname)
{
	int ret;

	/*
	 * If there is a ``write'' group, then only its members can write
	 * to the file system, no matter what the permission bits say.
	 *
	 * To users not in the ``write'' group, the file system appears
	 * read only.  This is used to serve sources.cs.bell-labs.com
	 * to the world.
	 *
	 * Note that if there is no ``write'' group, then this routine
	 * makes it look like everyone is a member -- the opposite
	 * of what groupMember does.
	 *
	 * We use this for sources.cs.bell-labs.com.
	 * If this slows things down too much on systems that don't
	 * use this functionality, we could cache the write group lookup.
	 */

	vtRLock(ubox.lock);
	ret = _groupMember(ubox.box, "write", uname, 1);
	vtRUnlock(ubox.lock);
	return ret;
}
예제 #4
0
파일: 9lstn.c 프로젝트: 99years/plan9
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;
}
예제 #5
0
파일: fs.c 프로젝트: bhanug/harvey
int
fsVac(Fs *fs, char *name, uint8_t score[VtScoreSize])
{
	int r;
	DirEntry de;
	Entry e, ee;
	File *f;

	vtRLock(fs->elk);
	f = fileOpen(fs, name);
	if(f == nil){
		vtRUnlock(fs->elk);
		return 0;
	}

	if(!fileGetSources(f, &e, &ee) || !fileGetDir(f, &de)){
		fileDecRef(f);
		vtRUnlock(fs->elk);
		return 0;
	}
	fileDecRef(f);

	r = mkVac(fs->z, fs->blockSize, &e, &ee, &de, score);
	vtRUnlock(fs->elk);
	return r;
}
예제 #6
0
파일: fs.c 프로젝트: bhanug/harvey
static int
fsNeedArch(Fs *fs, uint archMinute)
{
	int need;
	File *f;
	char buf[100];
	Tm now;
	uint32_t then;

	then = time(0);
	now = *localtime(then);

	/* back up to yesterday if necessary */
	if(now.hour < archMinute/60
	|| now.hour == archMinute/60 && now.min < archMinute%60)
		now = *localtime(then-86400);

	snprint(buf, sizeof buf, "/archive/%d/%02d%02d",
		now.year+1900, now.mon+1, now.mday);
	need = 1;
	vtRLock(fs->elk);
	f = fileOpen(fs, buf);
	if(f){
		need = 0;
		fileDecRef(f);
	}
	vtRUnlock(fs->elk);
	return need;
}
예제 #7
0
파일: 9user.c 프로젝트: 99years/plan9
int
groupLeader(char* group, char* member)
{
	int r;
	User *g;

	/*
	 * Is 'member' the leader of 'group'?
	 * Note that 'group' is a 'uid' and not a 'uname'.
	 * Uname 'none' cannot be a group leader.
	 */
	if(strcmp(member, unamenone) == 0 || group == nil)
		return 0;

	vtRLock(ubox.lock);
	if((g = _userByUid(ubox.box, group)) == nil){
		vtRUnlock(ubox.lock);
		return 0;
	}
	if(g->leader != nil){
		if(strcmp(g->leader, member) == 0){
			vtRUnlock(ubox.lock);
			return 1;
		}
		r = 0;
	}
	else
		r = _groupMember(ubox.box, group, member, 0);
	vtRUnlock(ubox.lock);

	return r;
}
예제 #8
0
static int
fileRLock(File *f)
{
	assert(!vtCanLock(f->fs->elk));
	vtRLock(f->lk);
	if(!chkSource(f)){
		fileRUnlock(f);
		return 0;
	}
	return 1;
}
예제 #9
0
파일: fs.c 프로젝트: bhanug/harvey
static void
fsMetaFlush(void *a)
{
	int rv;
	Fs *fs = a;

	vtRLock(fs->elk);
	rv = fileMetaFlush(fs->file, 1);
	vtRUnlock(fs->elk);
	if(rv > 0)
		cacheFlush(fs->cache, 0);
}
예제 #10
0
파일: 9user.c 프로젝트: 99years/plan9
int
groupMember(char* group, char* member)
{
	int r;

	if(group == nil)
		return 0;

	vtRLock(ubox.lock);
	r = _groupMember(ubox.box, group, member, 0);
	vtRUnlock(ubox.lock);

	return r;
}
예제 #11
0
파일: 9user.c 프로젝트: 99years/plan9
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;
}
예제 #12
0
파일: 9user.c 프로젝트: 99years/plan9
char*
uidByUname(char* uname)
{
	User *u;
	char *uid;

	vtRLock(ubox.lock);
	if((u = _userByUname(ubox.box, uname)) == nil){
		vtRUnlock(ubox.lock);
		return nil;
	}
	uid = vtStrDup(u->uid);
	vtRUnlock(ubox.lock);

	return uid;
}
예제 #13
0
파일: 9user.c 프로젝트: 99years/plan9
char*
unameByUid(char* uid)
{
	User *u;
	char *uname;

	vtRLock(ubox.lock);
	if((u = _userByUid(ubox.box, uid)) == nil){
		vtRUnlock(ubox.lock);
		return nil;
	}
	uname = vtStrDup(u->uname);
	vtRUnlock(ubox.lock);

	return uname;
}
예제 #14
0
파일: fs.c 프로젝트: bhanug/harvey
void
fsSnapshotCleanup(Fs *fs, uint32_t age)
{
	uint32_t lo;

	/*
	 * Find the best low epoch we can use,
	 * given that we need to save all the unventied archives
	 * and all the snapshots younger than age.
	 */
	vtRLock(fs->elk);
	lo = fs->ehi;
	fsEsearch(fs, "/archive", 0, &lo);
	fsEsearch(fs, "/snapshot", time(0)-age*60, &lo);
	vtRUnlock(fs->elk);

	fsEpochLow(fs, lo);
	fsSnapshotRemove(fs);
}
예제 #15
0
파일: fs.c 프로젝트: bhanug/harvey
void
fsClose(Fs *fs)
{
	vtRLock(fs->elk);
	periodicKill(fs->metaFlush);
	snapClose(fs->snap);
	if(fs->file){
		fileMetaFlush(fs->file, 0);
		if(!fileDecRef(fs->file))
			vtFatal("fsClose: files still in use: %r\n");
	}
	fs->file = nil;
	sourceClose(fs->source);
	cacheFree(fs->cache);
	if(fs->arch)
		archFree(fs->arch);
	vtMemFree(fs->name);
	vtRUnlock(fs->elk);
	vtLockFree(fs->elk);
	memset(fs, ~0, sizeof(Fs));
	vtMemFree(fs);
}
예제 #16
0
static void
topLevel(char *name)
{
	Fs *fs;
	File *root;

	/* ok, now we can open as a fs */
	fs = fsOpen(name, z, 100, OReadWrite);
	if(fs == nil)
		vtFatal("could not open file system: %r");
	vtRLock(fs->elk);
	root = fsGetRoot(fs);
	if(root == nil)
		vtFatal("could not open root: %r");
	addFile(root, "active", 0555);
	addFile(root, "archive", 0555);
	addFile(root, "snapshot", 0555);
	fileDecRef(root);
	if(iso9660file)
		iso9660copy(fs);
	vtRUnlock(fs->elk);
	fsClose(fs);
}
예제 #17
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;
}
예제 #18
0
파일: 9srv.c 프로젝트: aahud/harvey
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;
}
예제 #19
0
파일: 9user.c 프로젝트: 99years/plan9
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;
}