diff options
author | Bruce Momjian <bruce@momjian.us> | 2000-04-12 17:17:23 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2000-04-12 17:17:23 +0000 |
commit | 52f77df613cea1803ce86321c37229626d9f213c (patch) | |
tree | bd9ac9f667f295cb65f4c448a5bb5a062d656b27 /src/backend/commands/user.c | |
parent | db4518729d85da83eafdacbcebaeb12618517595 (diff) | |
download | postgresql-52f77df613cea1803ce86321c37229626d9f213c.tar.gz postgresql-52f77df613cea1803ce86321c37229626d9f213c.zip |
Ye-old pgindent run. Same 4-space tabs.
Diffstat (limited to 'src/backend/commands/user.c')
-rw-r--r-- | src/backend/commands/user.c | 1512 |
1 files changed, 774 insertions, 738 deletions
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 63676e14e48..fe24e15b1fd 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: user.c,v 1.51 2000/03/15 07:02:56 tgl Exp $ + * $Id: user.c,v 1.52 2000/04/12 17:14:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -55,11 +55,11 @@ write_password_file(Relation rel) char *filename, *tempname; int bufsize; - FILE *fp; - mode_t oumask; - HeapScanDesc scan; - HeapTuple tuple; - TupleDesc dsc = RelationGetDescr(rel); + FILE *fp; + mode_t oumask; + HeapScanDesc scan; + HeapTuple tuple; + TupleDesc dsc = RelationGetDescr(rel); /* * Create a temporary filename to be renamed later. This prevents the @@ -71,74 +71,85 @@ write_password_file(Relation rel) tempname = (char *) palloc(bufsize); snprintf(tempname, bufsize, "%s.%d", filename, MyProcPid); - oumask = umask((mode_t) 077); - fp = AllocateFile(tempname, "w"); - umask(oumask); - if (fp == NULL) - elog(ERROR, "%s: %s", tempname, strerror(errno)); - - /* read table */ - scan = heap_beginscan(rel, false, SnapshotSelf, 0, NULL); - while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) - { - Datum datum_n, datum_p, datum_v; - bool null_n, null_p, null_v; + oumask = umask((mode_t) 077); + fp = AllocateFile(tempname, "w"); + umask(oumask); + if (fp == NULL) + elog(ERROR, "%s: %s", tempname, strerror(errno)); + + /* read table */ + scan = heap_beginscan(rel, false, SnapshotSelf, 0, NULL); + while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) + { + Datum datum_n, + datum_p, + datum_v; + bool null_n, + null_p, + null_v; datum_n = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &null_n); - if (null_n) - continue; /* don't allow empty users */ + if (null_n) + continue; /* don't allow empty users */ datum_p = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &null_p); - /* It could be argued that people having a null password - shouldn't be allowed to connect, because they need - to have a password set up first. If you think assuming - an empty password in that case is better, erase the following line. */ - if (null_p) - continue; + + /* + * It could be argued that people having a null password shouldn't + * be allowed to connect, because they need to have a password set + * up first. If you think assuming an empty password in that case + * is better, erase the following line. + */ + if (null_p) + continue; datum_v = heap_getattr(tuple, Anum_pg_shadow_valuntil, dsc, &null_v); - /* These fake entries are not really necessary. To remove them, the parser - in backend/libpq/crypt.c would need to be adjusted. Initdb might also - need adjustments. */ - fprintf(fp, - "%s" - CRYPT_PWD_FILE_SEPSTR - "0" - CRYPT_PWD_FILE_SEPSTR - "x" - CRYPT_PWD_FILE_SEPSTR - "x" - CRYPT_PWD_FILE_SEPSTR - "x" - CRYPT_PWD_FILE_SEPSTR - "x" - CRYPT_PWD_FILE_SEPSTR - "%s" - CRYPT_PWD_FILE_SEPSTR - "%s\n", - nameout(DatumGetName(datum_n)), - null_p ? "" : textout((text*)datum_p), - null_v ? "\\N" : nabstimeout((AbsoluteTime)datum_v) /* this is how the parser wants it */ - ); - if (ferror(fp)) - elog(ERROR, "%s: %s", tempname, strerror(errno)); - fflush(fp); - } - heap_endscan(scan); - FreeFile(fp); - - /* - * And rename the temp file to its final name, deleting the old pg_pwd. - */ - rename(tempname, filename); - - /* + /* + * These fake entries are not really necessary. To remove them, + * the parser in backend/libpq/crypt.c would need to be adjusted. + * Initdb might also need adjustments. + */ + fprintf(fp, + "%s" + CRYPT_PWD_FILE_SEPSTR + "0" + CRYPT_PWD_FILE_SEPSTR + "x" + CRYPT_PWD_FILE_SEPSTR + "x" + CRYPT_PWD_FILE_SEPSTR + "x" + CRYPT_PWD_FILE_SEPSTR + "x" + CRYPT_PWD_FILE_SEPSTR + "%s" + CRYPT_PWD_FILE_SEPSTR + "%s\n", + nameout(DatumGetName(datum_n)), + null_p ? "" : textout((text *) datum_p), + null_v ? "\\N" : nabstimeout((AbsoluteTime) datum_v) /* this is how the + * parser wants it */ + ); + if (ferror(fp)) + elog(ERROR, "%s: %s", tempname, strerror(errno)); + fflush(fp); + } + heap_endscan(scan); + FreeFile(fp); + + /* + * And rename the temp file to its final name, deleting the old + * pg_pwd. + */ + rename(tempname, filename); + + /* * Create a flag file the postmaster will detect the next time it * tries to authenticate a user. The postmaster will know to reload * the pg_pwd file contents. */ filename = crypt_getpwdreloadfilename(); if (creat(filename, S_IRUSR | S_IWUSR) == -1) - elog(ERROR, "%s: %s", filename, strerror(errno)); + elog(ERROR, "%s: %s", filename, strerror(errno)); pfree((void *) tempname); } @@ -149,16 +160,17 @@ write_password_file(Relation rel) HeapTuple update_pg_pwd(void) { - Relation rel = heap_openr(ShadowRelationName, AccessExclusiveLock); - write_password_file(rel); - heap_close(rel, AccessExclusiveLock); + Relation rel = heap_openr(ShadowRelationName, AccessExclusiveLock); + + write_password_file(rel); + heap_close(rel, AccessExclusiveLock); /* - * This is a trigger, so clean out the information provided by - * the trigger manager. + * This is a trigger, so clean out the information provided by the + * trigger manager. */ CurrentTriggerData = NULL; - return NULL; + return NULL; } @@ -173,36 +185,37 @@ CreateUser(CreateUserStmt *stmt) TupleDesc pg_shadow_dsc; HeapScanDesc scan; HeapTuple tuple; - Datum new_record[Natts_pg_shadow]; - char new_record_nulls[Natts_pg_shadow]; + Datum new_record[Natts_pg_shadow]; + char new_record_nulls[Natts_pg_shadow]; bool user_exists = false, - sysid_exists = false, - havesysid; + sysid_exists = false, + havesysid; int max_id = -1; - List *item; + List *item; - havesysid = stmt->sysid > 0; + havesysid = stmt->sysid > 0; - /* Check some permissions first */ + /* Check some permissions first */ if (stmt->password) CheckPgUserAclNotNull(); - if (!superuser()) - elog(ERROR, "CREATE USER: permission denied"); + if (!superuser()) + elog(ERROR, "CREATE USER: permission denied"); - /* The reason for the following is this: - * If you start a transaction block, create a user, then roll back the - * transaction, the pg_pwd won't get rolled back due to a bug in the - * Unix file system ( :}). Hence this is in the interest of security. - */ + /* + * The reason for the following is this: If you start a transaction + * block, create a user, then roll back the transaction, the pg_pwd + * won't get rolled back due to a bug in the Unix file system ( :}). + * Hence this is in the interest of security. + */ if (IsTransactionBlock()) - elog(ERROR, "CREATE USER: may not be called in a transaction block"); + elog(ERROR, "CREATE USER: may not be called in a transaction block"); /* - * Scan the pg_shadow relation to be certain the user or id doesn't already - * exist. Note we secure exclusive lock, because we also need to be - * sure of what the next usesysid should be, and we need to protect - * our update of the flat password file. + * Scan the pg_shadow relation to be certain the user or id doesn't + * already exist. Note we secure exclusive lock, because we also need + * to be sure of what the next usesysid should be, and we need to + * protect our update of the flat password file. */ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); @@ -210,103 +223,108 @@ CreateUser(CreateUserStmt *stmt) scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL); while (!user_exists && !sysid_exists && HeapTupleIsValid(tuple = heap_getnext(scan, 0))) { - Datum datum; - bool null; + Datum datum; + bool null; datum = heap_getattr(tuple, Anum_pg_shadow_usename, pg_shadow_dsc, &null); user_exists = datum && !null && (strcmp((char *) datum, stmt->user) == 0); datum = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null); - if (havesysid) /* customized id wanted */ - sysid_exists = datum && !null && ((int)datum == stmt->sysid); - else /* pick 1 + max */ - { - if ((int) datum > max_id) - max_id = (int) datum; - } + if (havesysid) /* customized id wanted */ + sysid_exists = datum && !null && ((int) datum == stmt->sysid); + else +/* pick 1 + max */ + { + if ((int) datum > max_id) + max_id = (int) datum; + } } heap_endscan(scan); if (user_exists || sysid_exists) { heap_close(pg_shadow_rel, AccessExclusiveLock); - if (user_exists) - elog(ERROR, "CREATE USER: user name \"%s\" already exists", stmt->user); - else - elog(ERROR, "CREATE USER: sysid %d is already assigned", stmt->sysid); + if (user_exists) + elog(ERROR, "CREATE USER: user name \"%s\" already exists", stmt->user); + else + elog(ERROR, "CREATE USER: sysid %d is already assigned", stmt->sysid); return; } - /* - * Build a tuple to insert - */ - new_record[Anum_pg_shadow_usename-1] = PointerGetDatum(namein(stmt->user)); /* this truncated properly */ - new_record[Anum_pg_shadow_usesysid-1] = Int32GetDatum(havesysid ? stmt->sysid : max_id + 1); - - AssertState(BoolIsValid(stmt->createdb)); - new_record[Anum_pg_shadow_usecreatedb-1] = (Datum)(stmt->createdb); - new_record[Anum_pg_shadow_usetrace-1] = (Datum)(false); - AssertState(BoolIsValid(stmt->createuser)); - new_record[Anum_pg_shadow_usesuper-1] = (Datum)(stmt->createuser); - /* superuser gets catupd right by default */ - new_record[Anum_pg_shadow_usecatupd-1] = (Datum)(stmt->createuser); - - if (stmt->password) - new_record[Anum_pg_shadow_passwd-1] = PointerGetDatum(textin(stmt->password)); - if (stmt->validUntil) - new_record[Anum_pg_shadow_valuntil-1] = PointerGetDatum(nabstimein(stmt->validUntil)); - - new_record_nulls[Anum_pg_shadow_usename-1] = ' '; - new_record_nulls[Anum_pg_shadow_usesysid-1] = ' '; - - new_record_nulls[Anum_pg_shadow_usecreatedb-1] = ' '; - new_record_nulls[Anum_pg_shadow_usetrace-1] = ' '; - new_record_nulls[Anum_pg_shadow_usesuper-1] = ' '; - new_record_nulls[Anum_pg_shadow_usecatupd-1] = ' '; - - new_record_nulls[Anum_pg_shadow_passwd-1] = stmt->password ? ' ' : 'n'; - new_record_nulls[Anum_pg_shadow_valuntil-1] = stmt->validUntil ? ' ' : 'n'; - - tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls); - Assert(tuple); - - /* - * Insert a new record in the pg_shadow table - */ - if (heap_insert(pg_shadow_rel, tuple) == InvalidOid) - elog(ERROR, "CREATE USER: heap_insert failed"); - - /* - * Update indexes - */ - if (RelationGetForm(pg_shadow_rel)->relhasindex) { - Relation idescs[Num_pg_shadow_indices]; - - CatalogOpenIndices(Num_pg_shadow_indices, - Name_pg_shadow_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_shadow_indices, pg_shadow_rel, - tuple); - CatalogCloseIndices(Num_pg_shadow_indices, idescs); - } + /* + * Build a tuple to insert + */ + new_record[Anum_pg_shadow_usename - 1] = PointerGetDatum(namein(stmt->user)); /* this truncated + * properly */ + new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(havesysid ? stmt->sysid : max_id + 1); + + AssertState(BoolIsValid(stmt->createdb)); + new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (stmt->createdb); + new_record[Anum_pg_shadow_usetrace - 1] = (Datum) (false); + AssertState(BoolIsValid(stmt->createuser)); + new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (stmt->createuser); + /* superuser gets catupd right by default */ + new_record[Anum_pg_shadow_usecatupd - 1] = (Datum) (stmt->createuser); + + if (stmt->password) + new_record[Anum_pg_shadow_passwd - 1] = PointerGetDatum(textin(stmt->password)); + if (stmt->validUntil) + new_record[Anum_pg_shadow_valuntil - 1] = PointerGetDatum(nabstimein(stmt->validUntil)); + + new_record_nulls[Anum_pg_shadow_usename - 1] = ' '; + new_record_nulls[Anum_pg_shadow_usesysid - 1] = ' '; + + new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' '; + new_record_nulls[Anum_pg_shadow_usetrace - 1] = ' '; + new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' '; + new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' '; + + new_record_nulls[Anum_pg_shadow_passwd - 1] = stmt->password ? ' ' : 'n'; + new_record_nulls[Anum_pg_shadow_valuntil - 1] = stmt->validUntil ? ' ' : 'n'; + + tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls); + Assert(tuple); + + /* + * Insert a new record in the pg_shadow table + */ + if (heap_insert(pg_shadow_rel, tuple) == InvalidOid) + elog(ERROR, "CREATE USER: heap_insert failed"); + + /* + * Update indexes + */ + if (RelationGetForm(pg_shadow_rel)->relhasindex) + { + Relation idescs[Num_pg_shadow_indices]; + + CatalogOpenIndices(Num_pg_shadow_indices, + Name_pg_shadow_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_shadow_indices, pg_shadow_rel, + tuple); + CatalogCloseIndices(Num_pg_shadow_indices, idescs); + } /* * Add the user to the groups specified. We'll just call the below - * AlterGroup for this. + * AlterGroup for this. */ - foreach(item, stmt->groupElts) - { - AlterGroupStmt ags; + foreach(item, stmt->groupElts) + { + AlterGroupStmt ags; - ags.name = strVal(lfirst(item)); /* the group name to add this in */ - ags.action = +1; - ags.listUsers = lcons((void*)makeInteger(havesysid ? stmt->sysid : max_id + 1), NIL); - AlterGroup(&ags, "CREATE USER"); - } + ags.name = strVal(lfirst(item)); /* the group name to add + * this in */ + ags.action = +1; + ags.listUsers = lcons((void *) makeInteger(havesysid ? stmt->sysid : max_id + 1), NIL); + AlterGroup(&ags, "CREATE USER"); + } /* * Write the updated pg_shadow data to the flat password file. */ - write_password_file(pg_shadow_rel); + write_password_file(pg_shadow_rel); + /* * Now we can clean up. */ @@ -321,30 +339,31 @@ CreateUser(CreateUserStmt *stmt) extern void AlterUser(AlterUserStmt *stmt) { - Datum new_record[Natts_pg_shadow]; - char new_record_nulls[Natts_pg_shadow]; + Datum new_record[Natts_pg_shadow]; + char new_record_nulls[Natts_pg_shadow]; Relation pg_shadow_rel; TupleDesc pg_shadow_dsc; - HeapTuple tuple, new_tuple; - bool null; + HeapTuple tuple, + new_tuple; + bool null; if (stmt->password) CheckPgUserAclNotNull(); - /* must be superuser or just want to change your own password */ - if (!superuser() && - !(stmt->createdb==0 && stmt->createuser==0 && !stmt->validUntil - && stmt->password && strcmp(GetPgUserName(), stmt->user)==0)) - elog(ERROR, "ALTER USER: permission denied"); + /* must be superuser or just want to change your own password */ + if (!superuser() && + !(stmt->createdb == 0 && stmt->createuser == 0 && !stmt->validUntil + && stmt->password && strcmp(GetPgUserName(), stmt->user) == 0)) + elog(ERROR, "ALTER USER: permission denied"); - /* see comments in create user */ + /* see comments in create user */ if (IsTransactionBlock()) - elog(ERROR, "ALTER USER: may not be called in a transaction block"); + elog(ERROR, "ALTER USER: may not be called in a transaction block"); /* - * Scan the pg_shadow relation to be certain the user exists. - * Note we secure exclusive lock to protect our update of the - * flat password file. + * Scan the pg_shadow relation to be certain the user exists. Note we + * secure exclusive lock to protect our update of the flat password + * file. */ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); @@ -358,107 +377,107 @@ AlterUser(AlterUserStmt *stmt) elog(ERROR, "ALTER USER: user \"%s\" does not exist", stmt->user); } - /* - * Build a tuple to update, perusing the information just obtained - */ - new_record[Anum_pg_shadow_usename-1] = PointerGetDatum(namein(stmt->user)); - new_record_nulls[Anum_pg_shadow_usename-1] = ' '; - - /* sysid - leave as is */ - new_record[Anum_pg_shadow_usesysid-1] = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_usesysid-1] = null ? 'n' : ' '; - - /* createdb */ - if (stmt->createdb == 0) - { - /* don't change */ - new_record[Anum_pg_shadow_usecreatedb-1] = heap_getattr(tuple, Anum_pg_shadow_usecreatedb, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_usecreatedb-1] = null ? 'n' : ' '; - } - else - { - new_record[Anum_pg_shadow_usecreatedb-1] = (Datum)(stmt->createdb > 0 ? true : false); - new_record_nulls[Anum_pg_shadow_usecreatedb-1] = ' '; - } - - /* trace - leave as is */ - new_record[Anum_pg_shadow_usetrace-1] = heap_getattr(tuple, Anum_pg_shadow_usetrace, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_usetrace-1] = null ? 'n' : ' '; - - /* createuser (superuser) */ - if (stmt->createuser == 0) - { - /* don't change */ - new_record[Anum_pg_shadow_usesuper-1] = heap_getattr(tuple, Anum_pg_shadow_usesuper, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_usesuper-1] = null ? 'n' : ' '; - } - else - { - new_record[Anum_pg_shadow_usesuper-1] = (Datum)(stmt->createuser > 0 ? true : false); - new_record_nulls[Anum_pg_shadow_usesuper-1] = ' '; - } - - /* catupd - set to false if someone's superuser priv is being yanked */ - if (stmt->createuser < 0) - { - new_record[Anum_pg_shadow_usecatupd-1] = (Datum)(false); - new_record_nulls[Anum_pg_shadow_usecatupd-1] = ' '; - } - else - { - /* leave alone */ - new_record[Anum_pg_shadow_usecatupd-1] = heap_getattr(tuple, Anum_pg_shadow_usecatupd, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_usecatupd-1] = null ? 'n' : ' '; - } - - /* password */ - if (stmt->password) - { - new_record[Anum_pg_shadow_passwd-1] = PointerGetDatum(textin(stmt->password)); - new_record_nulls[Anum_pg_shadow_passwd-1] = ' '; - } - else - { - /* leave as is */ - new_record[Anum_pg_shadow_passwd-1] = heap_getattr(tuple, Anum_pg_shadow_passwd, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_passwd-1] = null ? 'n' : ' '; - } - - /* valid until */ - if (stmt->validUntil) - { - new_record[Anum_pg_shadow_valuntil-1] = PointerGetDatum(nabstimein(stmt->validUntil)); - new_record_nulls[Anum_pg_shadow_valuntil-1] = ' '; - } - else - { - /* leave as is */ - new_record[Anum_pg_shadow_valuntil-1] = heap_getattr(tuple, Anum_pg_shadow_valuntil, pg_shadow_dsc, &null); - new_record_nulls[Anum_pg_shadow_valuntil-1] = null ? 'n' : ' '; - } - - new_tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls); - Assert(new_tuple); - /* XXX check return value of this? */ - heap_update(pg_shadow_rel, &tuple->t_self, new_tuple, NULL); - - - /* Update indexes */ - if (RelationGetForm(pg_shadow_rel)->relhasindex) - { - Relation idescs[Num_pg_shadow_indices]; - - CatalogOpenIndices(Num_pg_shadow_indices, - Name_pg_shadow_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_shadow_indices, pg_shadow_rel, - tuple); - CatalogCloseIndices(Num_pg_shadow_indices, idescs); - } + /* + * Build a tuple to update, perusing the information just obtained + */ + new_record[Anum_pg_shadow_usename - 1] = PointerGetDatum(namein(stmt->user)); + new_record_nulls[Anum_pg_shadow_usename - 1] = ' '; + + /* sysid - leave as is */ + new_record[Anum_pg_shadow_usesysid - 1] = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_usesysid - 1] = null ? 'n' : ' '; + + /* createdb */ + if (stmt->createdb == 0) + { + /* don't change */ + new_record[Anum_pg_shadow_usecreatedb - 1] = heap_getattr(tuple, Anum_pg_shadow_usecreatedb, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = null ? 'n' : ' '; + } + else + { + new_record[Anum_pg_shadow_usecreatedb - 1] = (Datum) (stmt->createdb > 0 ? true : false); + new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' '; + } + + /* trace - leave as is */ + new_record[Anum_pg_shadow_usetrace - 1] = heap_getattr(tuple, Anum_pg_shadow_usetrace, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_usetrace - 1] = null ? 'n' : ' '; + + /* createuser (superuser) */ + if (stmt->createuser == 0) + { + /* don't change */ + new_record[Anum_pg_shadow_usesuper - 1] = heap_getattr(tuple, Anum_pg_shadow_usesuper, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_usesuper - 1] = null ? 'n' : ' '; + } + else + { + new_record[Anum_pg_shadow_usesuper - 1] = (Datum) (stmt->createuser > 0 ? true : false); + new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' '; + } + + /* catupd - set to false if someone's superuser priv is being yanked */ + if (stmt->createuser < 0) + { + new_record[Anum_pg_shadow_usecatupd - 1] = (Datum) (false); + new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' '; + } + else + { + /* leave alone */ + new_record[Anum_pg_shadow_usecatupd - 1] = heap_getattr(tuple, Anum_pg_shadow_usecatupd, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_usecatupd - 1] = null ? 'n' : ' '; + } + + /* password */ + if (stmt->password) + { + new_record[Anum_pg_shadow_passwd - 1] = PointerGetDatum(textin(stmt->password)); + new_record_nulls[Anum_pg_shadow_passwd - 1] = ' '; + } + else + { + /* leave as is */ + new_record[Anum_pg_shadow_passwd - 1] = heap_getattr(tuple, Anum_pg_shadow_passwd, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_passwd - 1] = null ? 'n' : ' '; + } + + /* valid until */ + if (stmt->validUntil) + { + new_record[Anum_pg_shadow_valuntil - 1] = PointerGetDatum(nabstimein(stmt->validUntil)); + new_record_nulls[Anum_pg_shadow_valuntil - 1] = ' '; + } + else + { + /* leave as is */ + new_record[Anum_pg_shadow_valuntil - 1] = heap_getattr(tuple, Anum_pg_shadow_valuntil, pg_shadow_dsc, &null); + new_record_nulls[Anum_pg_shadow_valuntil - 1] = null ? 'n' : ' '; + } + + new_tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls); + Assert(new_tuple); + /* XXX check return value of this? */ + heap_update(pg_shadow_rel, &tuple->t_self, new_tuple, NULL); + + + /* Update indexes */ + if (RelationGetForm(pg_shadow_rel)->relhasindex) + { + Relation idescs[Num_pg_shadow_indices]; + + CatalogOpenIndices(Num_pg_shadow_indices, + Name_pg_shadow_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_shadow_indices, pg_shadow_rel, + tuple); + CatalogCloseIndices(Num_pg_shadow_indices, idescs); + } /* * Write the updated pg_shadow data to the flat password file. */ - write_password_file(pg_shadow_rel); + write_password_file(pg_shadow_rel); /* * Now we can clean up. @@ -477,13 +496,13 @@ DropUser(DropUserStmt *stmt) { Relation pg_shadow_rel; TupleDesc pg_shadow_dsc; - List *item; + List *item; - if (!superuser()) - elog(ERROR, "DROP USER: permission denied"); + if (!superuser()) + elog(ERROR, "DROP USER: permission denied"); if (IsTransactionBlock()) - elog(ERROR, "DROP USER: may not be called in a transaction block"); + elog(ERROR, "DROP USER: may not be called in a transaction block"); /* * Scan the pg_shadow relation to find the usesysid of the user to be @@ -493,103 +512,105 @@ DropUser(DropUserStmt *stmt) pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); - foreach(item, stmt->users) - { - HeapTuple tuple, - tmp_tuple; - Relation pg_rel; - TupleDesc pg_dsc; - ScanKeyData scankey; - HeapScanDesc scan; - Datum datum; - bool null; - int32 usesysid; - const char *user = strVal(lfirst(item)); - - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(user), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_shadow_rel, AccessExclusiveLock); - elog(ERROR, "DROP USER: user \"%s\" does not exist%s", user, - (length(stmt->users) > 1) ? " (no users removed)" : ""); - } - - usesysid = DatumGetInt32(heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null)); - - /*------------------- - * Check if user still owns a database. If so, error out. - * - * (It used to be that this function would drop the database automatically. - * This is not only very dangerous for people that don't read the manual, - * it doesn't seem to be the behaviour one would expect either.) - * -- petere 2000/01/14) - *-------------------*/ - pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock); - pg_dsc = RelationGetDescr(pg_rel); - - ScanKeyEntryInitialize(&scankey, 0x0, Anum_pg_database_datdba, F_INT4EQ, - Int32GetDatum(usesysid)); - - scan = heap_beginscan(pg_rel, false, SnapshotNow, 1, &scankey); - - if (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0))) - { - datum = heap_getattr(tmp_tuple, Anum_pg_database_datname, pg_dsc, &null); - heap_close(pg_shadow_rel, AccessExclusiveLock); - elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s", - user, nameout(DatumGetName(datum)), - (length(stmt->users) > 1) ? " (no users removed)" : "" - ); - } - - heap_endscan(scan); - heap_close(pg_rel, AccessExclusiveLock); - - /* - * Somehow we'd have to check for tables, views, etc. owned by the user - * as well, but those could be spread out over all sorts of databases - * which we don't have access to (easily). - */ - - /* - * Remove the user from the pg_shadow table - */ - heap_delete(pg_shadow_rel, &tuple->t_self, NULL); - - /* - * Remove user from groups - * - * try calling alter group drop user for every group - */ - pg_rel = heap_openr(GroupRelationName, AccessExclusiveLock); - pg_dsc = RelationGetDescr(pg_rel); - scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL); - while (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0))) - { - AlterGroupStmt ags; - - datum = heap_getattr(tmp_tuple, Anum_pg_group_groname, pg_dsc, &null); - - ags.name = nameout(DatumGetName(datum)); /* the group name from which to try to drop the user */ - ags.action = -1; - ags.listUsers = lcons((void*)makeInteger(usesysid), NIL); - AlterGroup(&ags, "DROP USER"); - } - heap_endscan(scan); - heap_close(pg_rel, AccessExclusiveLock); - } + foreach(item, stmt->users) + { + HeapTuple tuple, + tmp_tuple; + Relation pg_rel; + TupleDesc pg_dsc; + ScanKeyData scankey; + HeapScanDesc scan; + Datum datum; + bool null; + int32 usesysid; + const char *user = strVal(lfirst(item)); + + tuple = SearchSysCacheTuple(SHADOWNAME, + PointerGetDatum(user), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + heap_close(pg_shadow_rel, AccessExclusiveLock); + elog(ERROR, "DROP USER: user \"%s\" does not exist%s", user, + (length(stmt->users) > 1) ? " (no users removed)" : ""); + } + + usesysid = DatumGetInt32(heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null)); + + /*------------------- + * Check if user still owns a database. If so, error out. + * + * (It used to be that this function would drop the database automatically. + * This is not only very dangerous for people that don't read the manual, + * it doesn't seem to be the behaviour one would expect either.) + * -- petere 2000/01/14) + *-------------------*/ + pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock); + pg_dsc = RelationGetDescr(pg_rel); + + ScanKeyEntryInitialize(&scankey, 0x0, Anum_pg_database_datdba, F_INT4EQ, + Int32GetDatum(usesysid)); + + scan = heap_beginscan(pg_rel, false, SnapshotNow, 1, &scankey); + + if (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0))) + { + datum = heap_getattr(tmp_tuple, Anum_pg_database_datname, pg_dsc, &null); + heap_close(pg_shadow_rel, AccessExclusiveLock); + elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s", + user, nameout(DatumGetName(datum)), + (length(stmt->users) > 1) ? " (no users removed)" : "" + ); + } + + heap_endscan(scan); + heap_close(pg_rel, AccessExclusiveLock); + + /* + * Somehow we'd have to check for tables, views, etc. owned by the + * user as well, but those could be spread out over all sorts of + * databases which we don't have access to (easily). + */ + + /* + * Remove the user from the pg_shadow table + */ + heap_delete(pg_shadow_rel, &tuple->t_self, NULL); + + /* + * Remove user from groups + * + * try calling alter group drop user for every group + */ + pg_rel = heap_openr(GroupRelationName, AccessExclusiveLock); + pg_dsc = RelationGetDescr(pg_rel); + scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL); + while (HeapTupleIsValid(tmp_tuple = heap_getnext(scan, 0))) + { + AlterGroupStmt ags; + + datum = heap_getattr(tmp_tuple, Anum_pg_group_groname, pg_dsc, &null); + + ags.name = nameout(DatumGetName(datum)); /* the group name from + * which to try to drop + * the user */ + ags.action = -1; + ags.listUsers = lcons((void *) makeInteger(usesysid), NIL); + AlterGroup(&ags, "DROP USER"); + } + heap_endscan(scan); + heap_close(pg_rel, AccessExclusiveLock); + } /* * Write the updated pg_shadow data to the flat password file. */ - write_password_file(pg_shadow_rel); + write_password_file(pg_shadow_rel); - /* - * Now we can clean up. - */ - heap_close(pg_shadow_rel, AccessExclusiveLock); + /* + * Now we can clean up. + */ + heap_close(pg_shadow_rel, AccessExclusiveLock); } @@ -609,7 +630,7 @@ CheckPgUserAclNotNull() 0, 0, 0); if (!HeapTupleIsValid(htup)) { - /* BIG problem */ + /* BIG problem */ elog(ERROR, "IsPgUserAclNull: \"%s\" not found", ShadowRelationName); } @@ -617,10 +638,10 @@ CheckPgUserAclNotNull() if (heap_attisnull(htup, Anum_pg_class_relacl)) { elog(ERROR, - "To use passwords, you have to revoke permissions on %s " - "so normal users cannot read the passwords. " - "Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.", - ShadowRelationName, ShadowRelationName); + "To use passwords, you have to revoke permissions on %s " + "so normal users cannot read the passwords. " + "Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.", + ShadowRelationName, ShadowRelationName); } return; @@ -637,14 +658,15 @@ CreateGroup(CreateGroupStmt *stmt) Relation pg_group_rel; HeapScanDesc scan; HeapTuple tuple; - TupleDesc pg_group_dsc; - bool group_exists = false, - sysid_exists = false; - int max_id = 0; - Datum new_record[Natts_pg_group]; - char new_record_nulls[Natts_pg_group]; - List *item, *newlist=NULL; - ArrayType *userarray; + TupleDesc pg_group_dsc; + bool group_exists = false, + sysid_exists = false; + int max_id = 0; + Datum new_record[Natts_pg_group]; + char new_record_nulls[Natts_pg_group]; + List *item, + *newlist = NULL; + ArrayType *userarray; /* * Make sure the user can do this. @@ -652,12 +674,12 @@ CreateGroup(CreateGroupStmt *stmt) if (!superuser()) elog(ERROR, "CREATE GROUP: permission denied"); - /* - * There is not real reason for this, but it makes it consistent - * with create user, and it seems like a good idea anyway. - */ + /* + * There is not real reason for this, but it makes it consistent with + * create user, and it seems like a good idea anyway. + */ if (IsTransactionBlock()) - elog(ERROR, "CREATE GROUP: may not be called in a transaction block"); + elog(ERROR, "CREATE GROUP: may not be called in a transaction block"); pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock); @@ -666,111 +688,111 @@ CreateGroup(CreateGroupStmt *stmt) scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL); while (!group_exists && !sysid_exists && HeapTupleIsValid(tuple = heap_getnext(scan, false))) { - Datum datum; - bool null; + Datum datum; + bool null; datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null); group_exists = datum && !null && (strcmp((char *) datum, stmt->name) == 0); datum = heap_getattr(tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); - if (stmt->sysid >= 0) /* customized id wanted */ - sysid_exists = datum && !null && ((int)datum == stmt->sysid); - else /* pick 1 + max */ - { - if ((int) datum > max_id) - max_id = (int) datum; - } + if (stmt->sysid >= 0) /* customized id wanted */ + sysid_exists = datum && !null && ((int) datum == stmt->sysid); + else +/* pick 1 + max */ + { + if ((int) datum > max_id) + max_id = (int) datum; + } } heap_endscan(scan); if (group_exists || sysid_exists) { heap_close(pg_group_rel, AccessExclusiveLock); - if (group_exists) - elog(ERROR, "CREATE GROUP: group name \"%s\" already exists", stmt->name); - else - elog(ERROR, "CREATE GROUP: group sysid %d is already assigned", stmt->sysid); + if (group_exists) + elog(ERROR, "CREATE GROUP: group name \"%s\" already exists", stmt->name); + else + elog(ERROR, "CREATE GROUP: group sysid %d is already assigned", stmt->sysid); } - /* - * Translate the given user names to ids - */ - - foreach(item, stmt->initUsers) - { - const char * groupuser = strVal(lfirst(item)); - Value *v; - - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(groupuser), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_group_rel, AccessExclusiveLock); - elog(ERROR, "CREATE GROUP: user \"%s\" does not exist", groupuser); - } - - v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); - if (!member(v, newlist)) - newlist = lcons(v, newlist); - } - - /* build an array to insert */ - if (newlist) - { - int i; - - userarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); - ARR_SIZE(userarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); - ARR_FLAGS(userarray) = 0x0; - ARR_NDIM(userarray) = 1; /* one dimensional array */ - ARR_LBOUND(userarray)[0] = 1; /* axis starts at one */ - ARR_DIMS(userarray)[0] = length(newlist); /* axis is this long */ - /* fill the array */ - i = 0; - foreach(item, newlist) - { - ((int*)ARR_DATA_PTR(userarray))[i++] = intVal(lfirst(item)); - } - } - else - userarray = NULL; - - /* - * Form a tuple to insert - */ - if (stmt->sysid >=0) - max_id = stmt->sysid; - else - max_id++; - - new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name); - new_record[Anum_pg_group_grosysid-1] = (Datum)(max_id); - new_record[Anum_pg_group_grolist-1] = (Datum)userarray; - - new_record_nulls[Anum_pg_group_groname-1] = ' '; - new_record_nulls[Anum_pg_group_grosysid-1] = ' '; - new_record_nulls[Anum_pg_group_grolist-1] = userarray ? ' ' : 'n'; - - tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); - - /* - * Insert a new record in the pg_group_table - */ - heap_insert(pg_group_rel, tuple); - - /* - * Update indexes - */ - if (RelationGetForm(pg_group_rel)->relhasindex) { - Relation idescs[Num_pg_group_indices]; - - CatalogOpenIndices(Num_pg_group_indices, - Name_pg_group_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, - tuple); - CatalogCloseIndices(Num_pg_group_indices, idescs); - } + /* + * Translate the given user names to ids + */ + + foreach(item, stmt->initUsers) + { + const char *groupuser = strVal(lfirst(item)); + Value *v; + + tuple = SearchSysCacheTuple(SHADOWNAME, + PointerGetDatum(groupuser), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + heap_close(pg_group_rel, AccessExclusiveLock); + elog(ERROR, "CREATE GROUP: user \"%s\" does not exist", groupuser); + } + + v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); + if (!member(v, newlist)) + newlist = lcons(v, newlist); + } + + /* build an array to insert */ + if (newlist) + { + int i; + + userarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); + ARR_SIZE(userarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); + ARR_FLAGS(userarray) = 0x0; + ARR_NDIM(userarray) = 1;/* one dimensional array */ + ARR_LBOUND(userarray)[0] = 1; /* axis starts at one */ + ARR_DIMS(userarray)[0] = length(newlist); /* axis is this long */ + /* fill the array */ + i = 0; + foreach(item, newlist) + ((int *) ARR_DATA_PTR(userarray))[i++] = intVal(lfirst(item)); + } + else + userarray = NULL; + + /* + * Form a tuple to insert + */ + if (stmt->sysid >= 0) + max_id = stmt->sysid; + else + max_id++; + + new_record[Anum_pg_group_groname - 1] = (Datum) (stmt->name); + new_record[Anum_pg_group_grosysid - 1] = (Datum) (max_id); + new_record[Anum_pg_group_grolist - 1] = (Datum) userarray; + + new_record_nulls[Anum_pg_group_groname - 1] = ' '; + new_record_nulls[Anum_pg_group_grosysid - 1] = ' '; + new_record_nulls[Anum_pg_group_grolist - 1] = userarray ? ' ' : 'n'; + + tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); + + /* + * Insert a new record in the pg_group_table + */ + heap_insert(pg_group_rel, tuple); + + /* + * Update indexes + */ + if (RelationGetForm(pg_group_rel)->relhasindex) + { + Relation idescs[Num_pg_group_indices]; + + CatalogOpenIndices(Num_pg_group_indices, + Name_pg_group_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, + tuple); + CatalogCloseIndices(Num_pg_group_indices, idescs); + } heap_close(pg_group_rel, AccessExclusiveLock); } @@ -781,258 +803,272 @@ CreateGroup(CreateGroupStmt *stmt) * ALTER GROUP */ void -AlterGroup(AlterGroupStmt *stmt, const char * tag) +AlterGroup(AlterGroupStmt *stmt, const char *tag) { Relation pg_group_rel; - TupleDesc pg_group_dsc; - HeapTuple group_tuple; + TupleDesc pg_group_dsc; + HeapTuple group_tuple; - /* + /* * Make sure the user can do this. */ if (!superuser()) elog(ERROR, "%s: permission denied", tag); - /* - * There is not real reason for this, but it makes it consistent - * with alter user, and it seems like a good idea anyway. - */ + /* + * There is not real reason for this, but it makes it consistent with + * alter user, and it seems like a good idea anyway. + */ if (IsTransactionBlock()) - elog(ERROR, "%s: may not be called in a transaction block", tag); + elog(ERROR, "%s: may not be called in a transaction block", tag); - pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock); - pg_group_dsc = RelationGetDescr(pg_group_rel); + pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock); + pg_group_dsc = RelationGetDescr(pg_group_rel); - /* - * Verify that group exists. - * If we find a tuple, will take that the rest of the way and make our - * modifications on it. - */ - if (!HeapTupleIsValid(group_tuple = SearchSysCacheTupleCopy(GRONAME, PointerGetDatum(stmt->name), 0, 0, 0))) + /* + * Verify that group exists. If we find a tuple, will take that the + * rest of the way and make our modifications on it. + */ + if (!HeapTupleIsValid(group_tuple = SearchSysCacheTupleCopy(GRONAME, PointerGetDatum(stmt->name), 0, 0, 0))) { - heap_close(pg_group_rel, AccessExclusiveLock); + heap_close(pg_group_rel, AccessExclusiveLock); elog(ERROR, "%s: group \"%s\" does not exist", tag, stmt->name); } - AssertState(stmt->action == +1 || stmt->action == -1); - /* - * Now decide what to do. - */ - if (stmt->action == +1) /* add users, might also be invoked by create user */ - { - Datum new_record[Natts_pg_group]; - char new_record_nulls[Natts_pg_group] = { ' ', ' ', ' '}; - ArrayType *newarray, *oldarray; - List * newlist = NULL, *item; - HeapTuple tuple; - bool null = false; - Datum datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null); - int i; - - oldarray = (ArrayType*)datum; - Assert(null || ARR_NDIM(oldarray) == 1); - /* first add the old array to the hitherto empty list */ - if (!null) - for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++) - { - int index, arrval; - Value *v; - bool valueNull; - index = i; - arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true/*by value*/, - sizeof(int), 0, &valueNull)); - v = makeInteger(arrval); - /* filter out duplicates */ - if (!member(v, newlist)) - newlist = lcons(v, newlist); - } - - /* - * now convert the to be added usernames to sysids and add them - * to the list - */ - foreach(item, stmt->listUsers) - { - Value *v; - - if (strcmp(tag, "ALTER GROUP")==0) - { - /* Get the uid of the proposed user to add. */ - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(strVal(lfirst(item))), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_group_rel, AccessExclusiveLock); - elog(ERROR, "%s: user \"%s\" does not exist", tag, strVal(lfirst(item))); - } - v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); - } - 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 */ - v = lfirst(item); - } - else + AssertState(stmt->action == +1 || stmt->action == -1); + + /* + * Now decide what to do. + */ + if (stmt->action == +1) /* add users, might also be invoked by + * create user */ + { + Datum new_record[Natts_pg_group]; + char new_record_nulls[Natts_pg_group] = {' ', ' ', ' '}; + ArrayType *newarray, + *oldarray; + List *newlist = NULL, + *item; + HeapTuple tuple; + bool null = false; + Datum datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null); + int i; + + oldarray = (ArrayType *) datum; + Assert(null || ARR_NDIM(oldarray) == 1); + /* first add the old array to the hitherto empty list */ + if (!null) + for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++) + { + int index, + arrval; + Value *v; + bool valueNull; + + index = i; + arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true /* by value */ , + sizeof(int), 0, &valueNull)); + v = makeInteger(arrval); + /* filter out duplicates */ + if (!member(v, newlist)) + newlist = lcons(v, newlist); + } + + /* + * now convert the to be added usernames to sysids and add them to + * the list + */ + foreach(item, stmt->listUsers) + { + Value *v; + + if (strcmp(tag, "ALTER GROUP") == 0) + { + /* Get the uid of the proposed user to add. */ + tuple = SearchSysCacheTuple(SHADOWNAME, + PointerGetDatum(strVal(lfirst(item))), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + heap_close(pg_group_rel, AccessExclusiveLock); + elog(ERROR, "%s: user \"%s\" does not exist", tag, strVal(lfirst(item))); + } + v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); + } + else if (strcmp(tag, "CREATE USER") == 0) { - elog(ERROR, "AlterGroup: unknown tag %s", tag); + + /* + * in this case we already know the uid and it wouldn't be + * in the cache anyway yet + */ + v = lfirst(item); + } + else + { + elog(ERROR, "AlterGroup: unknown tag %s", tag); v = NULL; /* keep compiler quiet */ } - if (!member(v, newlist)) - newlist = lcons(v, newlist); - else - /* we silently assume here that this error will only come up - in a ALTER GROUP statement */ - elog(NOTICE, "%s: user \"%s\" is already in group \"%s\"", tag, strVal(lfirst(item)), stmt->name); - } - - newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); - ARR_SIZE(newarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); - ARR_FLAGS(newarray) = 0x0; - ARR_NDIM(newarray) = 1; /* one dimensional array */ - ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */ - ARR_DIMS(newarray)[0] = length(newlist); /* axis is this long */ - /* fill the array */ - i = 0; - foreach(item, newlist) - { - ((int*)ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item)); - } - - /* - * Form a tuple with the new array and write it back. - */ - new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name); - new_record[Anum_pg_group_grosysid-1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); - new_record[Anum_pg_group_grolist-1] = PointerGetDatum(newarray); - - tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); - heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL); - - /* Update indexes */ - if (RelationGetForm(pg_group_rel)->relhasindex) { - Relation idescs[Num_pg_group_indices]; - - CatalogOpenIndices(Num_pg_group_indices, - Name_pg_group_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, - tuple); - CatalogCloseIndices(Num_pg_group_indices, idescs); - } - } /* endif alter group add user */ - - else if (stmt->action == -1) /*drop users from group */ - { - Datum datum; - bool null; - bool is_dropuser = strcmp(tag, "DROP USER")==0; - - datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null); - if (null) - { - if (!is_dropuser) - elog(NOTICE, "ALTER GROUP: group \"%s\" does not have any members", stmt->name); - } - else - { - HeapTuple tuple; - Datum new_record[Natts_pg_group]; - char new_record_nulls[Natts_pg_group] = { ' ', ' ', ' '}; - ArrayType *oldarray, *newarray; - List * newlist = NULL, *item; - int i; - - oldarray = (ArrayType*)datum; - Assert(ARR_NDIM(oldarray) == 1); - /* first add the old array to the hitherto empty list */ - for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++) - { - int index, arrval; - Value *v; - bool valueNull; - index = i; - arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true/*by value*/, - sizeof(int), 0, &valueNull)); - v = makeInteger(arrval); - /* filter out duplicates */ - if (!member(v, newlist)) - newlist = lcons(v, newlist); - } - - /* - * now convert the to be dropped usernames to sysids and remove - * them from the list - */ - foreach(item, stmt->listUsers) - { - Value *v; - if (!is_dropuser) - { - /* Get the uid of the proposed user to drop. */ - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(strVal(lfirst(item))), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_group_rel, AccessExclusiveLock); - elog(ERROR, "ALTER GROUP: user \"%s\" does not exist", strVal(lfirst(item))); - } - v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); - } - else - { - /* for dropuser we already know the uid */ - v = lfirst(item); - } - if (member(v, newlist)) - newlist = LispRemove(v, newlist); - else if (!is_dropuser) - elog(NOTICE, "ALTER GROUP: user \"%s\" is not in group \"%s\"", strVal(lfirst(item)), stmt->name); - } - - newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); - ARR_SIZE(newarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); - ARR_FLAGS(newarray) = 0x0; - ARR_NDIM(newarray) = 1; /* one dimensional array */ - ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */ - ARR_DIMS(newarray)[0] = length(newlist); /* axis is this long */ - /* fill the array */ - i = 0; - foreach(item, newlist) - { - ((int*)ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item)); - } - - /* - * Insert the new tuple with the updated user list - */ - new_record[Anum_pg_group_groname-1] = (Datum)(stmt->name); - new_record[Anum_pg_group_grosysid-1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); - new_record[Anum_pg_group_grolist-1] = PointerGetDatum(newarray); - - tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); - heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL); - - /* Update indexes */ - if (RelationGetForm(pg_group_rel)->relhasindex) { - Relation idescs[Num_pg_group_indices]; - - CatalogOpenIndices(Num_pg_group_indices, - Name_pg_group_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, - tuple); - CatalogCloseIndices(Num_pg_group_indices, idescs); - } - - } /* endif group not null */ - } /* endif alter group drop user */ - - heap_close(pg_group_rel, AccessExclusiveLock); - - pfree(group_tuple); + if (!member(v, newlist)) + newlist = lcons(v, newlist); + else + + /* + * we silently assume here that this error will only come + * up in a ALTER GROUP statement + */ + elog(NOTICE, "%s: user \"%s\" is already in group \"%s\"", tag, strVal(lfirst(item)), stmt->name); + } + + newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); + ARR_SIZE(newarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); + ARR_FLAGS(newarray) = 0x0; + ARR_NDIM(newarray) = 1; /* one dimensional array */ + ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */ + ARR_DIMS(newarray)[0] = length(newlist); /* axis is this long */ + /* fill the array */ + i = 0; + foreach(item, newlist) + ((int *) ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item)); + + /* + * Form a tuple with the new array and write it back. + */ + new_record[Anum_pg_group_groname - 1] = (Datum) (stmt->name); + new_record[Anum_pg_group_grosysid - 1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); + new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray); + + tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); + heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL); + + /* Update indexes */ + if (RelationGetForm(pg_group_rel)->relhasindex) + { + Relation idescs[Num_pg_group_indices]; + + CatalogOpenIndices(Num_pg_group_indices, + Name_pg_group_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, + tuple); + CatalogCloseIndices(Num_pg_group_indices, idescs); + } + } /* endif alter group add user */ + + else if (stmt->action == -1)/* drop users from group */ + { + Datum datum; + bool null; + bool is_dropuser = strcmp(tag, "DROP USER") == 0; + + datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null); + if (null) + { + if (!is_dropuser) + elog(NOTICE, "ALTER GROUP: group \"%s\" does not have any members", stmt->name); + } + else + { + HeapTuple tuple; + Datum new_record[Natts_pg_group]; + char new_record_nulls[Natts_pg_group] = {' ', ' ', ' '}; + ArrayType *oldarray, + *newarray; + List *newlist = NULL, + *item; + int i; + + oldarray = (ArrayType *) datum; + Assert(ARR_NDIM(oldarray) == 1); + /* first add the old array to the hitherto empty list */ + for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++) + { + int index, + arrval; + Value *v; + bool valueNull; + + index = i; + arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true /* by value */ , + sizeof(int), 0, &valueNull)); + v = makeInteger(arrval); + /* filter out duplicates */ + if (!member(v, newlist)) + newlist = lcons(v, newlist); + } + + /* + * now convert the to be dropped usernames to sysids and + * remove them from the list + */ + foreach(item, stmt->listUsers) + { + Value *v; + + if (!is_dropuser) + { + /* Get the uid of the proposed user to drop. */ + tuple = SearchSysCacheTuple(SHADOWNAME, + PointerGetDatum(strVal(lfirst(item))), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + heap_close(pg_group_rel, AccessExclusiveLock); + elog(ERROR, "ALTER GROUP: user \"%s\" does not exist", strVal(lfirst(item))); + } + v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); + } + else + { + /* for dropuser we already know the uid */ + v = lfirst(item); + } + if (member(v, newlist)) + newlist = LispRemove(v, newlist); + else if (!is_dropuser) + elog(NOTICE, "ALTER GROUP: user \"%s\" is not in group \"%s\"", strVal(lfirst(item)), stmt->name); + } + + newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); + ARR_SIZE(newarray) = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); + ARR_FLAGS(newarray) = 0x0; + ARR_NDIM(newarray) = 1; /* one dimensional array */ + ARR_LBOUND(newarray)[0] = 1; /* axis starts at one */ + ARR_DIMS(newarray)[0] = length(newlist); /* axis is this long */ + /* fill the array */ + i = 0; + foreach(item, newlist) + ((int *) ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item)); + + /* + * Insert the new tuple with the updated user list + */ + new_record[Anum_pg_group_groname - 1] = (Datum) (stmt->name); + new_record[Anum_pg_group_grosysid - 1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); + new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray); + + tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); + heap_update(pg_group_rel, &group_tuple->t_self, tuple, NULL); + + /* Update indexes */ + if (RelationGetForm(pg_group_rel)->relhasindex) + { + Relation idescs[Num_pg_group_indices]; + + CatalogOpenIndices(Num_pg_group_indices, + Name_pg_group_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, + tuple); + CatalogCloseIndices(Num_pg_group_indices, idescs); + } + + } /* endif group not null */ + } /* endif alter group drop user */ + + heap_close(pg_group_rel, AccessExclusiveLock); + + pfree(group_tuple); } @@ -1046,52 +1082,52 @@ DropGroup(DropGroupStmt *stmt) Relation pg_group_rel; HeapScanDesc scan; HeapTuple tuple; - TupleDesc pg_group_dsc; - bool gro_exists = false; + TupleDesc pg_group_dsc; + bool gro_exists = false; - /* + /* * Make sure the user can do this. */ if (!superuser()) elog(ERROR, "DROP GROUP: permission denied"); - /* - * There is not real reason for this, but it makes it consistent - * with drop user, and it seems like a good idea anyway. - */ + /* + * There is not real reason for this, but it makes it consistent with + * drop user, and it seems like a good idea anyway. + */ if (IsTransactionBlock()) - elog(ERROR, "DROP GROUP: may not be called in a transaction block"); + elog(ERROR, "DROP GROUP: may not be called in a transaction block"); - /* - * Scan the pg_group table and delete all matching groups. - */ + /* + * Scan the pg_group table and delete all matching groups. + */ pg_group_rel = heap_openr(GroupRelationName, AccessExclusiveLock); pg_group_dsc = RelationGetDescr(pg_group_rel); scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL); while (HeapTupleIsValid(tuple = heap_getnext(scan, false))) { - Datum datum; - bool null; - - datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null); - if (datum && !null && strcmp((char*)datum, stmt->name)==0) - { - gro_exists = true; - heap_delete(pg_group_rel, &tuple->t_self, NULL); - } + Datum datum; + bool null; + + datum = heap_getattr(tuple, Anum_pg_group_groname, pg_group_dsc, &null); + if (datum && !null && strcmp((char *) datum, stmt->name) == 0) + { + gro_exists = true; + heap_delete(pg_group_rel, &tuple->t_self, NULL); + } } heap_endscan(scan); - /* - * Did we find any? - */ - if (!gro_exists) - { - heap_close(pg_group_rel, AccessExclusiveLock); + /* + * Did we find any? + */ + if (!gro_exists) + { + heap_close(pg_group_rel, AccessExclusiveLock); elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name); - } + } heap_close(pg_group_rel, AccessExclusiveLock); } |