dbcommands.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:8k
- /*-------------------------------------------------------------------------
- *
- * dbcommands.c
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /usr/local/cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.35.2.1 1999/08/02 05:56:58 scrappy Exp $
- *
- *-------------------------------------------------------------------------
- */
- #include <signal.h>
- #include <sys/stat.h>
- #include "postgres.h"
- #include "access/heapam.h"
- #include "catalog/catname.h"
- #include "catalog/pg_database.h"
- #include "catalog/pg_shadow.h"
- #include "commands/dbcommands.h"
- #include "miscadmin.h"
- #include "tcop/tcopprot.h"
- #include "utils/syscache.h"
- /* non-export function prototypes */
- static void check_permissions(char *command, char *dbpath, char *dbname,
- Oid *dbIdP, int4 *userIdP);
- static HeapTuple get_pg_dbtup(char *command, char *dbname, Relation dbrel);
- static void stop_vacuum(char *dbpath, char *dbname);
- void
- createdb(char *dbname, char *dbpath, int encoding, CommandDest dest)
- {
- Oid db_id;
- int4 user_id;
- char buf[512];
- char *lp,
- loc[512];
- /*
- * If this call returns, the database does not exist and we're allowed
- * to create databases.
- */
- check_permissions("createdb", dbpath, dbname, &db_id, &user_id);
- /* close virtual file descriptors so we can do system() calls */
- closeAllVfds();
- /* Now create directory for this new database */
- if ((dbpath != NULL) && (strcmp(dbpath, dbname) != 0))
- {
- if (*(dbpath + strlen(dbpath) - 1) == SEP_CHAR)
- *(dbpath + strlen(dbpath) - 1) = ' ';
- snprintf(loc, 512, "%s%c%s", dbpath, SEP_CHAR, dbname);
- }
- else
- strcpy(loc, dbname);
- lp = ExpandDatabasePath(loc);
- if (lp == NULL)
- elog(ERROR, "Unable to locate path '%s'"
- "ntThis may be due to a missing environment variable"
- " in the server", loc);
- if (mkdir(lp, S_IRWXU) != 0)
- elog(ERROR, "Unable to create database directory '%s'", lp);
- snprintf(buf, 512, "%s %s%cbase%ctemplate1%c* %s",
- COPY_CMD, DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, lp);
- system(buf);
- snprintf(buf, 512,
- "insert into pg_database (datname, datdba, encoding, datpath)"
- " values ('%s', '%d', '%d', '%s');", dbname, user_id, encoding,
- loc);
- pg_exec_query_dest(buf, dest, false);
- }
- void
- destroydb(char *dbname, CommandDest dest)
- {
- int4 user_id;
- Oid db_id;
- char *path,
- dbpath[MAXPGPATH + 1],
- buf[512];
- /*
- * If this call returns, the database exists and we're allowed to
- * remove it.
- */
- check_permissions("destroydb", dbpath, dbname, &db_id, &user_id);
- if (!OidIsValid(db_id))
- elog(FATAL, "pg_database instance has an invalid OID");
- /* stop the vacuum daemon */
- stop_vacuum(dbpath, dbname);
- path = ExpandDatabasePath(dbpath);
- if (path == NULL)
- elog(ERROR, "Unable to locate path '%s'"
- "ntThis may be due to a missing environment variable"
- " in the server", dbpath);
- /*
- * remove the pg_database tuple FIRST, this may fail due to
- * permissions problems
- */
- snprintf(buf, 512,
- "delete from pg_database where pg_database.oid = '%u'::oid", db_id);
- pg_exec_query_dest(buf, dest, false);
- /* drop pages for this database that are in the shared buffer cache */
- DropBuffers(db_id);
- /*
- * remove the data directory. If the DELETE above failed, this will
- * not be reached
- */
- snprintf(buf, 512, "rm -r %s", path);
- system(buf);
- }
- static HeapTuple
- get_pg_dbtup(char *command, char *dbname, Relation dbrel)
- {
- HeapTuple dbtup;
- HeapTuple tup;
- HeapScanDesc scan;
- ScanKeyData scanKey;
- ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
- F_NAMEEQ, NameGetDatum(dbname));
- scan = heap_beginscan(dbrel, 0, SnapshotNow, 1, &scanKey);
- if (!HeapScanIsValid(scan))
- elog(ERROR, "%s: cannot begin scan of pg_database", command);
- /*
- * since we want to return the tuple out of this proc, and we're going
- * to close the relation, copy the tuple and return the copy.
- */
- tup = heap_getnext(scan, 0);
- if (HeapTupleIsValid(tup))
- dbtup = heap_copytuple(tup);
- else
- dbtup = tup;
- heap_endscan(scan);
- return dbtup;
- }
- /*
- * check_permissions() -- verify that the user is permitted to do this.
- *
- * If the user is not allowed to carry out this operation, this routine
- * elog(ERROR, ...)s, which will abort the xact. As a side effect, the
- * user's pg_user tuple OID is returned in userIdP and the target database's
- * OID is returned in dbIdP.
- */
- static void
- check_permissions(char *command,
- char *dbpath,
- char *dbname,
- Oid *dbIdP,
- int4 *userIdP)
- {
- Relation dbrel;
- HeapTuple dbtup,
- utup;
- int4 dbowner = 0;
- char use_createdb;
- bool dbfound;
- bool use_super;
- char *userName;
- text *dbtext;
- char path[MAXPGPATH + 1];
- userName = GetPgUserName();
- utup = SearchSysCacheTuple(USENAME,
- PointerGetDatum(userName),
- 0, 0, 0);
- *userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid;
- use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
- use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb;
- /* Check to make sure user has permission to use createdb */
- if (!use_createdb)
- {
- elog(ERROR, "user '%s' is not allowed to create/destroy databases",
- userName);
- }
- /* Make sure we are not mucking with the template database */
- if (!strcmp(dbname, "template1"))
- elog(ERROR, "%s: cannot be executed on the template database", command);
- /* Check to make sure database is not the currently open database */
- if (!strcmp(dbname, DatabaseName))
- elog(ERROR, "%s: cannot be executed on an open database", command);
- /* Check to make sure database is owned by this user */
- /*
- * need the reldesc to get the database owner out of dbtup and to set
- * a write lock on it.
- */
- dbrel = heap_openr(DatabaseRelationName);
- if (!RelationIsValid(dbrel))
- elog(FATAL, "%s: cannot open relation "%-.*s"",
- command, DatabaseRelationName);
- /*
- * Acquire a write lock on pg_database from the beginning to avoid
- * upgrading a read lock to a write lock. Upgrading causes long
- * delays when multiple 'createdb's or 'destroydb's are run simult.
- * -mer 7/3/91
- */
- LockRelation(dbrel, AccessExclusiveLock);
- dbtup = get_pg_dbtup(command, dbname, dbrel);
- dbfound = HeapTupleIsValid(dbtup);
- if (dbfound)
- {
- dbowner = (int4) heap_getattr(dbtup,
- Anum_pg_database_datdba,
- RelationGetDescr(dbrel),
- (char *) NULL);
- *dbIdP = dbtup->t_data->t_oid;
- dbtext = (text *) heap_getattr(dbtup,
- Anum_pg_database_datpath,
- RelationGetDescr(dbrel),
- (char *) NULL);
- strncpy(path, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ));
- *(path + VARSIZE(dbtext) - VARHDRSZ) = ' ';
- }
- else
- *dbIdP = InvalidOid;
- heap_close(dbrel);
- /*
- * Now be sure that the user is allowed to do this.
- */
- if (dbfound && !strcmp(command, "createdb"))
- {
- elog(ERROR, "createdb: database '%s' already exists", dbname);
- }
- else if (!dbfound && !strcmp(command, "destroydb"))
- {
- elog(ERROR, "destroydb: database '%s' does not exist", dbname);
- }
- else if (dbfound && !strcmp(command, "destroydb")
- && dbowner != *userIdP && use_super == false)
- {
- elog(ERROR, "%s: database '%s' is not owned by you", command, dbname);
- }
- if (dbfound && !strcmp(command, "destroydb"))
- strcpy(dbpath, path);
- } /* check_permissions() */
- /*
- * stop_vacuum() -- stop the vacuum daemon on the database, if one is running.
- */
- static void
- stop_vacuum(char *dbpath, char *dbname)
- {
- char filename[256];
- FILE *fp;
- int pid;
- if (strchr(dbpath, SEP_CHAR) != 0)
- {
- snprintf(filename, 256, "%s%cbase%c%s%c%s.vacuum",
- DataDir, SEP_CHAR, SEP_CHAR, dbname, SEP_CHAR, dbname);
- }
- else
- snprintf(filename, 256, "%s%c%s.vacuum", dbpath, SEP_CHAR, dbname);
- #ifndef __CYGWIN32__
- if ((fp = AllocateFile(filename, "r")) != NULL)
- #else
- if ((fp = AllocateFile(filename, "rb")) != NULL)
- #endif
- {
- fscanf(fp, "%d", &pid);
- FreeFile(fp);
- if (kill(pid, SIGKILLDAEMON1) < 0)
- {
- elog(ERROR, "can't kill vacuum daemon (pid %d) on '%s'",
- pid, dbname);
- }
- }
- }