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

📄 acl.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * acl.c *	  Basic access control list data structures manipulation routines. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.37.2.1 1999/08/02 05:24:49 scrappy Exp $ * *------------------------------------------------------------------------- */#include <ctype.h>#include "postgres.h"#include "catalog/catalog.h"#include "catalog/pg_shadow.h"#include "catalog/pg_type.h"#include "miscadmin.h"#include "utils/acl.h"#include "utils/memutils.h"#include "utils/syscache.h"static char *getid(char *s, char *n);static int32 aclitemeq(AclItem *a1, AclItem *a2);static int32 aclitemgt(AclItem *a1, AclItem *a2);static char *aclparse(char *s, AclItem *aip, unsigned *modechg);#define ACL_IDTYPE_GID_KEYWORD	"group"#define ACL_IDTYPE_UID_KEYWORD	"user"/* * getid *		Consumes the first alphanumeric string (identifier) found in string *		's', ignoring any leading white space.	If it finds a double quote *		it returns the word inside the quotes. * * RETURNS: *		the string position in 's' that points to the next non-space character *		in 's', after any quotes.  Also: *		- loads the identifier into 'name'.  (If no identifier is found, 'name' *		  contains an empty string). */static char *getid(char *s, char *n){	unsigned	len;	char	   *id;	int			in_quotes = 0;	Assert(s && n);	while (isspace(*s))		++s;	if (*s == '"')	{		in_quotes = 1;		s++;	}	for (id = s, len = 0; isalnum(*s) || *s == '_' || in_quotes; ++len, ++s)	{		if (in_quotes && *s == '"')		{			len--;			in_quotes = 0;		}	}	if (len > sizeof(NameData))		elog(ERROR, "getid: identifier cannot be >%d characters",			 sizeof(NameData));	if (len > 0)		memmove(n, id, len);	n[len] = '\0';	while (isspace(*s))		++s;	return s;}/* * aclparse *		Consumes and parses an ACL specification of the form: *				[group|user] [A-Za-z0-9]*[+-=][rwaR]* *		from string 's', ignoring any leading white space or white space *		between the optional id type keyword (group|user) and the actual *		ACL specification. * *		This routine is called by the parser as well as aclitemin(), hence *		the added generality. * * RETURNS: *		the string position in 's' immediately following the ACL *		specification.	Also: *		- loads the structure pointed to by 'aip' with the appropriate *		  UID/GID, id type identifier and mode type values. *		- loads 'modechg' with the mode change flag. */static char *aclparse(char *s, AclItem *aip, unsigned *modechg){	HeapTuple	htup;	char		name[NAMEDATALEN];	Assert(s && aip && modechg);#ifdef ACLDEBUG_TRACE	printf("aclparse: input = '%s'\n", s);#endif	aip->ai_idtype = ACL_IDTYPE_UID;	s = getid(s, name);	if (*s != ACL_MODECHG_ADD_CHR &&		*s != ACL_MODECHG_DEL_CHR &&		*s != ACL_MODECHG_EQL_CHR)	{		/* we just read a keyword, not a name */		if (!strcmp(name, ACL_IDTYPE_GID_KEYWORD))			aip->ai_idtype = ACL_IDTYPE_GID;		else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD))			elog(ERROR, "aclparse: bad keyword, must be [group|user]");		s = getid(s, name);		/* move s to the name beyond the keyword */		if (name[0] == '\0')			elog(ERROR, "aclparse: a name must follow the [group|user] keyword");	}	if (name[0] == '\0')		aip->ai_idtype = ACL_IDTYPE_WORLD;	switch (*s)	{		case ACL_MODECHG_ADD_CHR:			*modechg = ACL_MODECHG_ADD;			break;		case ACL_MODECHG_DEL_CHR:			*modechg = ACL_MODECHG_DEL;			break;		case ACL_MODECHG_EQL_CHR:			*modechg = ACL_MODECHG_EQL;			break;		default:			elog(ERROR, "aclparse: mode change flag must use \"%s\"",				 ACL_MODECHG_STR);	}	aip->ai_mode = ACL_NO;	while (isalpha(*++s))	{		switch (*s)		{			case ACL_MODE_AP_CHR:				aip->ai_mode |= ACL_AP;				break;			case ACL_MODE_RD_CHR:				aip->ai_mode |= ACL_RD;				break;			case ACL_MODE_WR_CHR:				aip->ai_mode |= ACL_WR;				break;			case ACL_MODE_RU_CHR:				aip->ai_mode |= ACL_RU;				break;			default:				elog(ERROR, "aclparse: mode flags must use \"%s\"",					 ACL_MODE_STR);		}	}	switch (aip->ai_idtype)	{		case ACL_IDTYPE_UID:			htup = SearchSysCacheTuple(USENAME,									   PointerGetDatum(name),									   0, 0, 0);			if (!HeapTupleIsValid(htup))				elog(ERROR, "aclparse: non-existent user \"%s\"", name);			aip->ai_id = ((Form_pg_shadow) GETSTRUCT(htup))->usesysid;			break;		case ACL_IDTYPE_GID:			aip->ai_id = get_grosysid(name);			break;		case ACL_IDTYPE_WORLD:			aip->ai_id = ACL_ID_WORLD;			break;	}#ifdef ACLDEBUG_TRACE	elog(DEBUG, "aclparse: correctly read [%x %d %x], modechg=%x",		 aip->ai_idtype, aip->ai_id, aip->ai_mode, *modechg);#endif	return s;}/* * makeacl *		Allocates storage for a new Acl with 'n' entries. * * RETURNS: *		the new Acl */Acl *makeacl(int n){	Acl		   *new_acl;	Size		size;	if (n < 0)		elog(ERROR, "makeacl: invalid size: %d\n", n);	size = ACL_N_SIZE(n);	if (!(new_acl = (Acl *) palloc(size)))		elog(ERROR, "makeacl: palloc failed on %d\n", size);	MemSet((char *) new_acl, 0, size);	new_acl->size = size;	new_acl->ndim = 1;	new_acl->flags = 0;	ARR_LBOUND(new_acl)[0] = 0;	ARR_DIMS(new_acl)[0] = n;	return new_acl;}/* * aclitemin *		Allocates storage for, and fills in, a new AclItem given a string *		's' that contains an ACL specification.  See aclparse for details. * * RETURNS: *		the new AclItem */AclItem    *aclitemin(char *s){	unsigned	modechg;	AclItem    *aip;	if (!s)		elog(ERROR, "aclitemin: null string");	aip = (AclItem *) palloc(sizeof(AclItem));	if (!aip)		elog(ERROR, "aclitemin: palloc failed");	s = aclparse(s, aip, &modechg);	if (modechg != ACL_MODECHG_EQL)		elog(ERROR, "aclitemin: cannot accept anything but = ACLs");	while (isspace(*s))		++s;	if (*s)		elog(ERROR, "aclitemin: extra garbage at end of specification");	return aip;}/* * aclitemout *		Allocates storage for, and fills in, a new null-delimited string *		containing a formatted ACL specification.  See aclparse for details. * * RETURNS: *		the new string */char *aclitemout(AclItem *aip){	char	   *p;	char	   *out;	HeapTuple	htup;	unsigned	i;	static AclItem default_aclitem = {ACL_ID_WORLD,		ACL_IDTYPE_WORLD,	ACL_WORLD_DEFAULT};	extern char *int2out();	char	   *tmpname;	if (!aip)		aip = &default_aclitem;	p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN);	if (!out)		elog(ERROR, "aclitemout: palloc failed");	*p = '\0';	switch (aip->ai_idtype)	{		case ACL_IDTYPE_UID:			htup = SearchSysCacheTuple(USESYSID,									   ObjectIdGetDatum(aip->ai_id),									   0, 0, 0);			if (!HeapTupleIsValid(htup))			{				char	   *tmp = int2out(aip->ai_id);#ifdef NOT_USED				When this	elog(NOTICE) goes to the libpq client,							it crashes the							client because the NOTICE protocol is coming right in the middle							of a request for a field value.We skip the NOTICE for now.							elog(NOTICE, "aclitemout: usesysid %d not found",											 aip->ai_id);#endif				strcat(p, tmp);				pfree(tmp);			}			else				strncat(p, (char *) &((Form_pg_shadow)									  GETSTRUCT(htup))->usename,						sizeof(NameData));			break;		case ACL_IDTYPE_GID:			strcat(p, "group ");			tmpname = get_groname(aip->ai_id);			strncat(p, tmpname, NAMEDATALEN);			break;		case ACL_IDTYPE_WORLD:			break;		default:			elog(ERROR, "aclitemout: bad ai_idtype: %d", aip->ai_idtype);			break;	}	while (*p)		++p;	*p++ = '=';	for (i = 0; i < N_ACL_MODES; ++i)		if ((aip->ai_mode >> i) & 01)			*p++ = ACL_MODE_STR[i];	*p = '\0';	return out;}/* * aclitemeq * aclitemgt *		AclItem equality and greater-than comparison routines. *		Two AclItems are equal iff they are both NULL or they have the *		same identifier (and identifier type). * * RETURNS: *		a boolean value indicating = or > */static int32aclitemeq(AclItem *a1, AclItem *a2){	if (!a1 && !a2)		return 1;	if (!a1 || !a2)		return 0;	return a1->ai_idtype == a2->ai_idtype && a1->ai_id == a2->ai_id;}static int32aclitemgt(AclItem *a1, AclItem *a2){	if (a1 && !a2)		return 1;	if (!a1 || !a2)

⌨️ 快捷键说明

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