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

📄 user.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (!HeapTupleIsValid(tup))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("user \"%s\" does not exist", oldname)));	/*	 * XXX Client applications probably store the session user somewhere,	 * so renaming it could cause confusion.  On the other hand, there may	 * not be an actual problem besides a little confusion, so think about	 * this and decide.	 */	if (((Form_pg_shadow) GETSTRUCT(tup))->usesysid == GetSessionUserId())		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("session user may not be renamed")));	/* make sure the new name doesn't exist */	if (SearchSysCacheExists(SHADOWNAME,							 CStringGetDatum(newname),							 0, 0, 0))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("user \"%s\" already exists", newname)));	/* must be superuser */	if (!superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to rename users")));	/* rename */	namestrcpy(&(((Form_pg_shadow) GETSTRUCT(tup))->usename), newname);	simple_heap_update(rel, &tup->t_self, tup);	CatalogUpdateIndexes(rel, tup);	heap_close(rel, NoLock);	heap_freetuple(tup);	user_file_update_needed = true;}/* * CheckPgUserAclNotNull * * check to see if there is an ACL on pg_shadow */static voidCheckPgUserAclNotNull(void){	HeapTuple	htup;	htup = SearchSysCache(RELOID,						  ObjectIdGetDatum(RelOid_pg_shadow),						  0, 0, 0);	if (!HeapTupleIsValid(htup))	/* should not happen, we hope */		elog(ERROR, "cache lookup failed for relation %u", RelOid_pg_shadow);	if (heap_attisnull(htup, Anum_pg_class_relacl))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),		errmsg("before using passwords you must revoke privileges on %s",			   ShadowRelationName),				 errdetail("This restriction is to prevent unprivileged users from reading the passwords."),				 errhint("Try REVOKE ALL ON \"%s\" FROM PUBLIC.",						 ShadowRelationName)));	ReleaseSysCache(htup);}/* * CREATE GROUP */voidCreateGroup(CreateGroupStmt *stmt){	Relation	pg_group_rel;	HeapScanDesc scan;	HeapTuple	tuple;	TupleDesc	pg_group_dsc;	bool		group_exists = false,				sysid_exists = false,				havesysid = false;	int			max_id;	Datum		new_record[Natts_pg_group];	char		new_record_nulls[Natts_pg_group];	List	   *item,			   *option,			   *newlist = NIL;	IdList	   *grolist;	int			sysid = 0;	List	   *userElts = NIL;	DefElem    *dsysid = NULL;	DefElem    *duserElts = NULL;	foreach(option, stmt->options)	{		DefElem    *defel = (DefElem *) lfirst(option);		if (strcmp(defel->defname, "sysid") == 0)		{			if (dsysid)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			dsysid = defel;		}		else if (strcmp(defel->defname, "userElts") == 0)		{			if (duserElts)				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),						 errmsg("conflicting or redundant options")));			duserElts = defel;		}		else			elog(ERROR, "option \"%s\" not recognized",				 defel->defname);	}	if (dsysid)	{		sysid = intVal(dsysid->arg);		if (sysid <= 0)			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("group ID must be positive")));		havesysid = true;	}	if (duserElts)		userElts = (List *) duserElts->arg;	/*	 * Make sure the user can do this.	 */	if (!superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to create groups")));	if (strcmp(stmt->name, "public") == 0)		ereport(ERROR,				(errcode(ERRCODE_RESERVED_NAME),				 errmsg("group name \"%s\" is reserved",						stmt->name)));	/*	 * Scan the pg_group relation to be certain the group or id doesn't	 * already exist.  Note we secure exclusive lock, because we also need	 * to be sure of what the next grosysid should be, and we need to	 * protect our eventual update of the flat group file.	 */	pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);	pg_group_dsc = RelationGetDescr(pg_group_rel);	scan = heap_beginscan(pg_group_rel, SnapshotNow, 0, NULL);	max_id = 99;				/* start auto-assigned ids at 100 */	while (!group_exists && !sysid_exists &&		   (tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		Form_pg_group group_form = (Form_pg_group) GETSTRUCT(tuple);		int32		this_sysid;		group_exists = (strcmp(NameStr(group_form->groname), stmt->name) == 0);		this_sysid = group_form->grosysid;		if (havesysid)			/* customized id wanted */			sysid_exists = (this_sysid == sysid);		else		{			/* pick 1 + max */			if (this_sysid > max_id)				max_id = this_sysid;		}	}	heap_endscan(scan);	if (group_exists)		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("group \"%s\" already exists",						stmt->name)));	if (sysid_exists)		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("group ID %d is already assigned", sysid)));	/* If no sysid given, use max existing id + 1 */	if (!havesysid)		sysid = max_id + 1;	/*	 * Translate the given user names to ids	 */	foreach(item, userElts)	{		const char *groupuser = strVal(lfirst(item));		int32		userid = get_usesysid(groupuser);		if (!intMember(userid, newlist))			newlist = lappendi(newlist, userid);	}	/* build an array to insert */	if (newlist)		grolist = IdListToArray(newlist);	else		grolist = NULL;	/*	 * Form a tuple to insert	 */	new_record[Anum_pg_group_groname - 1] =		DirectFunctionCall1(namein, CStringGetDatum(stmt->name));	new_record[Anum_pg_group_grosysid - 1] = Int32GetDatum(sysid);	new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(grolist);	new_record_nulls[Anum_pg_group_groname - 1] = ' ';	new_record_nulls[Anum_pg_group_grosysid - 1] = ' ';	new_record_nulls[Anum_pg_group_grolist - 1] = grolist ? ' ' : 'n';	tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls);	/*	 * Insert a new record in the pg_group table	 */	simple_heap_insert(pg_group_rel, tuple);	/* Update indexes */	CatalogUpdateIndexes(pg_group_rel, tuple);	/*	 * Now we can clean up; but keep lock until commit (to avoid possible	 * deadlock when commit code tries to acquire lock).	 */	heap_close(pg_group_rel, NoLock);	/*	 * Set flag to update flat group file at commit.	 */	group_file_update_needed = true;}/* * ALTER GROUP */voidAlterGroup(AlterGroupStmt *stmt, const char *tag){	Relation	pg_group_rel;	TupleDesc	pg_group_dsc;	HeapTuple	group_tuple;	IdList	   *oldarray;	Datum		datum;	bool		null;	List	   *newlist,			   *item;	/*	 * Make sure the user can do this.	 */	if (!superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to alter groups")));	/*	 * Secure exclusive lock to protect our update of the flat group file.	 */	pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);	pg_group_dsc = RelationGetDescr(pg_group_rel);	/*	 * Fetch existing tuple for group.	 */	group_tuple = SearchSysCache(GRONAME,								 PointerGetDatum(stmt->name),								 0, 0, 0);	if (!HeapTupleIsValid(group_tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("group \"%s\" does not exist", stmt->name)));	/* Fetch old group membership. */	datum = heap_getattr(group_tuple, Anum_pg_group_grolist,						 pg_group_dsc, &null);	oldarray = null ? ((IdList *) NULL) : DatumGetIdListP(datum);	/* initialize list with old array contents */	newlist = IdArrayToList(oldarray);	/*	 * Now decide what to do.	 */	AssertState(stmt->action == +1 || stmt->action == -1);	if (stmt->action == +1)		/* add users, might also be invoked by								 * create user */	{		/*		 * convert the to be added usernames to sysids and add them to the		 * list		 */		foreach(item, stmt->listUsers)		{			int32		sysid;			if (strcmp(tag, "ALTER GROUP") == 0)			{				/* Get the uid of the proposed user to add. */				sysid = get_usesysid(strVal(lfirst(item)));			}			else if (strcmp(tag, "CREATE USER") == 0)			{				/*				 * in this case we already know the uid and it wouldn't be				 * in the cache anyway yet				 */				sysid = intVal(lfirst(item));			}			else			{				elog(ERROR, "unexpected tag: \"%s\"", tag);				sysid = 0;		/* keep compiler quiet */			}			if (!intMember(sysid, newlist))				newlist = lappendi(newlist, sysid);		}		/* Do the update */		UpdateGroupMembership(pg_group_rel, group_tuple, newlist);	}							/* endif alter group add user */	else if (stmt->action == -1)	/* drop users from group */	{		bool		is_dropuser = strcmp(tag, "DROP USER") == 0;		if (newlist == NIL)		{			if (!is_dropuser)				ereport(WARNING,						(errcode(ERRCODE_WARNING),						 errmsg("group \"%s\" does not have any members",								stmt->name)));		}		else		{			/*			 * convert the to be dropped usernames to sysids and remove			 * them from the list			 */			foreach(item, stmt->listUsers)			{				int32		sysid;				if (!is_dropuser)				{					/* Get the uid of the proposed user to drop. */					sysid = get_usesysid(strVal(lfirst(item)));				}				else				{					/* for dropuser we already know the uid */					sysid = intVal(lfirst(item));				}				if (intMember(sysid, newlist))					newlist = lremovei(sysid, newlist);				else if (!is_dropuser)					ereport(WARNING,							(errcode(ERRCODE_WARNING),							 errmsg("user \"%s\" is not in group \"%s\"",									strVal(lfirst(item)), stmt->name)));			}			/* Do the update */			UpdateGroupMembership(pg_group_rel, group_tuple, newlist);		}						/* endif group not null */	}							/* endif alter group drop user */	ReleaseSysCache(group_tuple);	/*	 * Now we can clean up; but keep lock until commit (to avoid possible	 * deadlock when commit code tries to acquire lock).	 */	heap_close(pg_group_rel, NoLock);	/*	 * Set flag to update flat group file at commit.	 */	group_file_update_needed = true;}/* * Subroutine for AlterGroup: given a pg_group tuple and a desired new * membership (expressed as an integer list), form and write an updated tuple. * The pg_group relation must be open and locked already. */static voidUpdateGroupMembership(Relation group_rel, HeapTuple group_tuple,					  List *members){	IdList	   *newarray;	Datum		new_record[Natts_pg_group];	char		new_record_nulls[Natts_pg_group];	char		new_record_repl[Natts_pg_group];	HeapTuple	tuple;	newarray = IdListToArray(members);	/*	 * Form an updated tuple with the new array and write it back.	 */	MemSet(new_record, 0, sizeof(new_record));	MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));	MemSet(new_record_repl, ' ', sizeof(new_record_repl));	new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray);	new_record_repl[Anum_pg_group_grolist - 1] = 'r';	tuple = heap_modifytuple(group_tuple, group_rel,						  new_record, new_record_nulls, new_record_repl);	simple_heap_update(group_rel, &group_tuple->t_self, tuple);	/* Update indexes */	CatalogUpdateIndexes(group_rel, tuple);}/* * Convert an integer list of sysids to an array. */static IdList *IdListToArray(List *members){	int			nmembers = length(members);	IdList	   *newarray;	List	   *item;	int			i;	newarray = palloc(ARR_OVERHEAD(1) + nmembers * sizeof(int32));	newarray->size = ARR_OVERHEAD(1) + nmembers * sizeof(int32);	newarray->flags = 0;	newarray->elemtype = INT4OID;	ARR_NDIM(newarray) = 1;		/* one dimensional array */	ARR_LBOUND(newarray)[0] = 1;	/* axis starts at one */	ARR_DIMS(newarray)[0] = nmembers;	/* axis is this long */	i = 0;	foreach(item, members)		((int *) ARR_DATA_PTR(newarray))[i++] = lfirsti(item);	return newarray;}/* * Convert an array of sysids to an integer list. */static List *IdArrayToList(IdList *oldarray){	List	   *newlist = NIL;	int			hibound,				i;	if (oldarray == NULL)		return NIL;	Assert(ARR_NDIM(oldarray) == 1);	Assert(ARR_ELEMTYPE(oldarray) == INT4OID);	hibound = ARR_DIMS(oldarray)[0];	for (i = 0; i < hibound; i++)	{		int32		sysid;		sysid = ((int32 *) ARR_DATA_PTR(oldarray))[i];		/* filter out any duplicates --- probably a waste of time */		if (!intMember(sysid, newlist))			newlist = lappendi(newlist, sysid);	}	return newlist;}/* * DROP GROUP */voidDropGroup(DropGroupStmt *stmt){	Relation	pg_group_rel;	HeapTuple	tuple;	/*	 * Make sure the user can do this.	 */	if (!superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to drop groups")));	/*	 * Secure exclusive lock to protect our update of the flat group file.	 */	pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock);	/* Find and delete the group. */	tuple = SearchSysCacheCopy(GRONAME,							   PointerGetDatum(stmt->name),							   0, 0, 0);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("group \"%s\" does not exist", stmt->name)));	simple_heap_delete(pg_group_rel, &tuple->t_self);	/*	 * Now we can clean up; but keep lock until commit (to avoid possible	 * deadlock when commit code tries to acquire lock).	 */	heap_close(pg_group_rel, NoLock);	/*	 * Set flag to update flat group file at commit.	 */	group_file_update_needed = true;}/* * Rename group */voidRenameGroup(const char *oldname, const char *newname){	HeapTuple	tup;	Relation	rel;	/* ExclusiveLock because we need to update the flat group file */	rel = heap_openr(GroupRelationName, ExclusiveLock);	tup = SearchSysCacheCopy(GRONAME,							 CStringGetDatum(oldname),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("group \"%s\" does not exist", oldname)));	/* make sure the new name doesn't exist */	if (SearchSysCacheExists(GRONAME,							 CStringGetDatum(newname),							 0, 0, 0))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_OBJECT),				 errmsg("group \"%s\" already exists", newname)));	/* must be superuser */	if (!superuser())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("must be superuser to rename groups")));	/* rename */	namestrcpy(&(((Form_pg_group) GETSTRUCT(tup))->groname), newname);	simple_heap_update(rel, &tup->t_self, tup);	CatalogUpdateIndexes(rel, tup);	heap_close(rel, NoLock);	heap_freetuple(tup);	group_file_update_needed = true;}

⌨️ 快捷键说明

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