⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 9user.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "stdinc.h"#include "9.h"enum {	NUserHash	= 1009,};typedef struct Ubox Ubox;typedef struct User User;typedef struct User {	char*	uid;	char*	uname;	char*	leader;	char**	group;	int	ngroup;	User*	next;			/* */	User*	ihash;			/* lookup by .uid */	User*	nhash;			/* lookup by .uname */} User;#pragma varargck type "U"   User*typedef struct Ubox {	User*	head;	User*	tail;	int	nuser;	int	len;	User*	ihash[NUserHash];	/* lookup by .uid */	User*	nhash[NUserHash];	/* lookup by .uname */} Ubox;static struct {	VtLock*	lock;	Ubox*	box;} ubox;static char usersDefault[] = {	"adm:adm:adm:sys\n"	"none:none::\n"	"noworld:noworld::\n"	"sys:sys::glenda\n"	"glenda:glenda:glenda:\n"};static char* usersMandatory[] = {	"adm",	"none",	"noworld",	"sys",	nil,};char* uidadm = "adm";char* unamenone = "none";char* uidnoworld = "noworld";static u32intuserHash(char* s){	uchar *p;	u32int hash;	hash = 0;	for(p = (uchar*)s; *p != '\0'; p++)		hash = hash*7 + *p;	return hash % NUserHash;}static User*_userByUid(Ubox* box, char* uid){	User *u;	if(box != nil){		for(u = box->ihash[userHash(uid)]; u != nil; u = u->ihash){			if(strcmp(u->uid, uid) == 0)				return u;		}	}	vtSetError("uname: uid '%s' not found", uid);	return nil;}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;}static User*_userByUname(Ubox* box, char* uname){	User *u;	if(box != nil){		for(u = box->nhash[userHash(uname)]; u != nil; u = u->nhash){			if(strcmp(u->uname, uname) == 0)				return u;		}	}	vtSetError("uname: uname '%s' not found", uname);	return nil;}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;}static int_groupMember(Ubox* box, char* group, char* member, int whenNoGroup){	int i;	User *g, *m;	/*	 * Is 'member' a member of 'group'?	 * Note that 'group' is a 'uid' and not a 'uname'.	 * A 'member' is automatically in their own group.	 */	if((g = _userByUid(box, group)) == nil)		return whenNoGroup;	if((m = _userByUname(box, member)) == nil)		return 0;	if(m == g)		return 1;	for(i = 0; i < g->ngroup; i++){		if(strcmp(g->group[i], member) == 0)			return 1;	}	return 0;}intgroupWriteMember(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;}static int_groupRemMember(Ubox* box, User* g, char* member){	int i;	if(_userByUname(box, member) == nil)		return 0;	for(i = 0; i < g->ngroup; i++){		if(strcmp(g->group[i], member) == 0)			break;	}	if(i >= g->ngroup){		if(strcmp(g->uname, member) == 0)			vtSetError("uname: '%s' always in own group", member);		else			vtSetError("uname: '%s' not in group '%s'",				member, g->uname);		return 0;	}	vtMemFree(g->group[i]);	box->len -= strlen(member);	if(g->ngroup > 1)		box->len--;	g->ngroup--;	switch(g->ngroup){	case 0:		vtMemFree(g->group);		g->group = nil;		break;	default:		while(i < g->ngroup){			g->group[i] = g->group[i+1];			i++;		}		/*FALLTHROUGH*/	case 1:		g->group = vtMemRealloc(g->group, (g->ngroup)*sizeof(char*));		break;	}	return 1;}static int_groupAddMember(Ubox* box, User* g, char* member){	User *u;	if((u = _userByUname(box, member)) == nil)		return 0;	if(_groupMember(box, g->uid, u->uname, 0)){		if(strcmp(g->uname, member) == 0)			vtSetError("uname: '%s' always in own group", member);		else			vtSetError("uname: '%s' already in group '%s'",				member, g->uname);		return 0;	}	g->group = vtMemRealloc(g->group, (g->ngroup+1)*sizeof(char*));	g->group[g->ngroup] = vtStrDup(member);	box->len += strlen(member);	g->ngroup++;	if(g->ngroup > 1)		box->len++;	return 1;}intgroupMember(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;}intgroupLeader(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;}static voiduserFree(User* u){	int i;	vtMemFree(u->uid);	vtMemFree(u->uname);	if(u->leader != nil)		vtMemFree(u->leader);	if(u->ngroup){		for(i = 0; i < u->ngroup; i++)			vtMemFree(u->group[i]);		vtMemFree(u->group);	}	vtMemFree(u);}static User*userAlloc(char* uid, char* uname){	User *u;	u = vtMemAllocZ(sizeof(User));	u->uid = vtStrDup(uid);	u->uname = vtStrDup(uname);	return u;}intvalidUserName(char* name){	Rune *r;	static Rune invalid[] = L"#:,()";	for(r = invalid; *r != '\0'; r++){		if(utfrune(name, *r))			return 0;	}	return 1;}static intuserFmt(Fmt* fmt){	User *u;	int i, r;	u = va_arg(fmt->args, User*);	r = fmtprint(fmt, "%s:%s:", u->uid, u->uname);	if(u->leader != nil)		r += fmtprint(fmt, u->leader);	r += fmtprint(fmt, ":");	if(u->ngroup){		r += fmtprint(fmt, u->group[0]);		for(i = 1; i < u->ngroup; i++)			r += fmtprint(fmt, ",%s", u->group[i]);	}	return r;}static intusersFileWrite(Ubox* box){	Fs *fs;	User *u;	int i, r;	Fsys *fsys;	char *p, *q, *s;	File *dir, *file;	if((fsys = fsysGet("main")) == nil)		return 0;	fsysFsRlock(fsys);	fs = fsysGetFs(fsys);	/*	 * BUG:	 * 	the owner/group/permissions need to be thought out.	 */	r = 0;	if((dir = fileOpen(fs, "/active")) == nil)		goto tidy0;	if((file = fileWalk(dir, uidadm)) == nil)		file = fileCreate(dir, uidadm, ModeDir|0775, uidadm);	fileDecRef(dir);	if(file == nil)		goto tidy;	dir = file;	if((file = fileWalk(dir, "users")) == nil)		file = fileCreate(dir, "users", 0664, uidadm);	fileDecRef(dir);	if(file == nil)		goto tidy;	if(!fileTruncate(file, uidadm))		goto tidy;	p = s = vtMemAlloc(box->len+1);	q = p + box->len+1;	for(u = box->head; u != nil; u = u->next){		p += snprint(p, q-p, "%s:%s:", u->uid, u->uname);		if(u->leader != nil)			p+= snprint(p, q-p, u->leader);		p += snprint(p, q-p, ":");		if(u->ngroup){			p += snprint(p, q-p, u->group[0]);			for(i = 1; i < u->ngroup; i++)				p += snprint(p, q-p, ",%s", u->group[i]);		}		p += snprint(p, q-p, "\n");	}	r = fileWrite(file, s, box->len, 0, uidadm);	vtMemFree(s);tidy:	if(file != nil)		fileDecRef(file);tidy0:	fsysFsRUnlock(fsys);	fsysPut(fsys);	return r;}static voiduboxRemUser(Ubox* box, User *u){	User **h, *up;	h = &box->ihash[userHash(u->uid)];	for(up = *h; up != nil && up != u; up = up->ihash)		h = &up->ihash;	assert(up == u);	*h = up->ihash;	box->len -= strlen(u->uid);	h = &box->nhash[userHash(u->uname)];	for(up = *h; up != nil && up != u; up = up->nhash)		h = &up->nhash;	assert(up == u);	*h = up->nhash;	box->len -= strlen(u->uname);	h = &box->head;	for(up = *h; up != nil && strcmp(up->uid, u->uid) != 0; up = up->next)		h = &up->next;	assert(up == u);	*h = u->next;	u->next = nil;	box->len -= 4;	box->nuser--;}static voiduboxAddUser(Ubox* box, User* u){	User **h, *up;	h = &box->ihash[userHash(u->uid)];	u->ihash = *h;	*h = u;	box->len += strlen(u->uid);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -