dbcommands.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:8k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * dbcommands.c
  4.  *
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.35.2.1 1999/08/02 05:56:58 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <signal.h>
  15. #include <sys/stat.h>
  16. #include "postgres.h"
  17. #include "access/heapam.h"
  18. #include "catalog/catname.h"
  19. #include "catalog/pg_database.h"
  20. #include "catalog/pg_shadow.h"
  21. #include "commands/dbcommands.h"
  22. #include "miscadmin.h"
  23. #include "tcop/tcopprot.h"
  24. #include "utils/syscache.h"
  25. /* non-export function prototypes */
  26. static void check_permissions(char *command, char *dbpath, char *dbname,
  27.   Oid *dbIdP, int4 *userIdP);
  28. static HeapTuple get_pg_dbtup(char *command, char *dbname, Relation dbrel);
  29. static void stop_vacuum(char *dbpath, char *dbname);
  30. void
  31. createdb(char *dbname, char *dbpath, int encoding, CommandDest dest)
  32. {
  33. Oid db_id;
  34. int4 user_id;
  35. char buf[512];
  36. char    *lp,
  37. loc[512];
  38. /*
  39.  * If this call returns, the database does not exist and we're allowed
  40.  * to create databases.
  41.  */
  42. check_permissions("createdb", dbpath, dbname, &db_id, &user_id);
  43. /* close virtual file descriptors so we can do system() calls */
  44. closeAllVfds();
  45. /* Now create directory for this new database */
  46. if ((dbpath != NULL) && (strcmp(dbpath, dbname) != 0))
  47. {
  48. if (*(dbpath + strlen(dbpath) - 1) == SEP_CHAR)
  49. *(dbpath + strlen(dbpath) - 1) = '';
  50. snprintf(loc, 512, "%s%c%s", dbpath, SEP_CHAR, dbname);
  51. }
  52. else
  53. strcpy(loc, dbname);
  54. lp = ExpandDatabasePath(loc);
  55. if (lp == NULL)
  56. elog(ERROR, "Unable to locate path '%s'"
  57.  "ntThis may be due to a missing environment variable"
  58.  " in the server", loc);
  59. if (mkdir(lp, S_IRWXU) != 0)
  60. elog(ERROR, "Unable to create database directory '%s'", lp);
  61. snprintf(buf, 512, "%s %s%cbase%ctemplate1%c* %s",
  62.  COPY_CMD, DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, lp);
  63. system(buf);
  64. snprintf(buf, 512,
  65.    "insert into pg_database (datname, datdba, encoding, datpath)"
  66.   " values ('%s', '%d', '%d', '%s');", dbname, user_id, encoding,
  67.  loc);
  68. pg_exec_query_dest(buf, dest, false);
  69. }
  70. void
  71. destroydb(char *dbname, CommandDest dest)
  72. {
  73. int4 user_id;
  74. Oid db_id;
  75. char    *path,
  76. dbpath[MAXPGPATH + 1],
  77. buf[512];
  78. /*
  79.  * If this call returns, the database exists and we're allowed to
  80.  * remove it.
  81.  */
  82. check_permissions("destroydb", dbpath, dbname, &db_id, &user_id);
  83. if (!OidIsValid(db_id))
  84. elog(FATAL, "pg_database instance has an invalid OID");
  85. /* stop the vacuum daemon */
  86. stop_vacuum(dbpath, dbname);
  87. path = ExpandDatabasePath(dbpath);
  88. if (path == NULL)
  89. elog(ERROR, "Unable to locate path '%s'"
  90.  "ntThis may be due to a missing environment variable"
  91.  " in the server", dbpath);
  92. /*
  93.  * remove the pg_database tuple FIRST, this may fail due to
  94.  * permissions problems
  95.  */
  96. snprintf(buf, 512,
  97. "delete from pg_database where pg_database.oid = '%u'::oid", db_id);
  98. pg_exec_query_dest(buf, dest, false);
  99. /* drop pages for this database that are in the shared buffer cache */
  100. DropBuffers(db_id);
  101. /*
  102.  * remove the data directory. If the DELETE above failed, this will
  103.  * not be reached
  104.  */
  105. snprintf(buf, 512, "rm -r %s", path);
  106. system(buf);
  107. }
  108. static HeapTuple
  109. get_pg_dbtup(char *command, char *dbname, Relation dbrel)
  110. {
  111. HeapTuple dbtup;
  112. HeapTuple tup;
  113. HeapScanDesc scan;
  114. ScanKeyData scanKey;
  115. ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
  116.    F_NAMEEQ, NameGetDatum(dbname));
  117. scan = heap_beginscan(dbrel, 0, SnapshotNow, 1, &scanKey);
  118. if (!HeapScanIsValid(scan))
  119. elog(ERROR, "%s: cannot begin scan of pg_database", command);
  120. /*
  121.  * since we want to return the tuple out of this proc, and we're going
  122.  * to close the relation, copy the tuple and return the copy.
  123.  */
  124. tup = heap_getnext(scan, 0);
  125. if (HeapTupleIsValid(tup))
  126. dbtup = heap_copytuple(tup);
  127. else
  128. dbtup = tup;
  129. heap_endscan(scan);
  130. return dbtup;
  131. }
  132. /*
  133.  * check_permissions() -- verify that the user is permitted to do this.
  134.  *
  135.  * If the user is not allowed to carry out this operation, this routine
  136.  * elog(ERROR, ...)s, which will abort the xact.  As a side effect, the
  137.  * user's pg_user tuple OID is returned in userIdP and the target database's
  138.  * OID is returned in dbIdP.
  139.  */
  140. static void
  141. check_permissions(char *command,
  142.   char *dbpath,
  143.   char *dbname,
  144.   Oid *dbIdP,
  145.   int4 *userIdP)
  146. {
  147. Relation dbrel;
  148. HeapTuple dbtup,
  149. utup;
  150. int4 dbowner = 0;
  151. char use_createdb;
  152. bool dbfound;
  153. bool use_super;
  154. char    *userName;
  155. text    *dbtext;
  156. char path[MAXPGPATH + 1];
  157. userName = GetPgUserName();
  158. utup = SearchSysCacheTuple(USENAME,
  159.    PointerGetDatum(userName),
  160.    0, 0, 0);
  161. *userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid;
  162. use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
  163. use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb;
  164. /* Check to make sure user has permission to use createdb */
  165. if (!use_createdb)
  166. {
  167. elog(ERROR, "user '%s' is not allowed to create/destroy databases",
  168.  userName);
  169. }
  170. /* Make sure we are not mucking with the template database */
  171. if (!strcmp(dbname, "template1"))
  172. elog(ERROR, "%s: cannot be executed on the template database", command);
  173. /* Check to make sure database is not the currently open database */
  174. if (!strcmp(dbname, DatabaseName))
  175. elog(ERROR, "%s: cannot be executed on an open database", command);
  176. /* Check to make sure database is owned by this user */
  177. /*
  178.  * need the reldesc to get the database owner out of dbtup and to set
  179.  * a write lock on it.
  180.  */
  181. dbrel = heap_openr(DatabaseRelationName);
  182. if (!RelationIsValid(dbrel))
  183. elog(FATAL, "%s: cannot open relation "%-.*s"",
  184.  command, DatabaseRelationName);
  185. /*
  186.  * Acquire a write lock on pg_database from the beginning to avoid
  187.  * upgrading a read lock to a write lock.  Upgrading causes long
  188.  * delays when multiple 'createdb's or 'destroydb's are run simult.
  189.  * -mer 7/3/91
  190.  */
  191. LockRelation(dbrel, AccessExclusiveLock);
  192. dbtup = get_pg_dbtup(command, dbname, dbrel);
  193. dbfound = HeapTupleIsValid(dbtup);
  194. if (dbfound)
  195. {
  196. dbowner = (int4) heap_getattr(dbtup,
  197.   Anum_pg_database_datdba,
  198.   RelationGetDescr(dbrel),
  199.   (char *) NULL);
  200. *dbIdP = dbtup->t_data->t_oid;
  201. dbtext = (text *) heap_getattr(dbtup,
  202.    Anum_pg_database_datpath,
  203.    RelationGetDescr(dbrel),
  204.    (char *) NULL);
  205. strncpy(path, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ));
  206. *(path + VARSIZE(dbtext) - VARHDRSZ) = '';
  207. }
  208. else
  209. *dbIdP = InvalidOid;
  210. heap_close(dbrel);
  211. /*
  212.  * Now be sure that the user is allowed to do this.
  213.  */
  214. if (dbfound && !strcmp(command, "createdb"))
  215. {
  216. elog(ERROR, "createdb: database '%s' already exists", dbname);
  217. }
  218. else if (!dbfound && !strcmp(command, "destroydb"))
  219. {
  220. elog(ERROR, "destroydb: database '%s' does not exist", dbname);
  221. }
  222. else if (dbfound && !strcmp(command, "destroydb")
  223.  && dbowner != *userIdP && use_super == false)
  224. {
  225. elog(ERROR, "%s: database '%s' is not owned by you", command, dbname);
  226. }
  227. if (dbfound && !strcmp(command, "destroydb"))
  228. strcpy(dbpath, path);
  229. } /* check_permissions() */
  230. /*
  231.  * stop_vacuum() -- stop the vacuum daemon on the database, if one is running.
  232.  */
  233. static void
  234. stop_vacuum(char *dbpath, char *dbname)
  235. {
  236. char filename[256];
  237. FILE    *fp;
  238. int pid;
  239. if (strchr(dbpath, SEP_CHAR) != 0)
  240. {
  241. snprintf(filename, 256, "%s%cbase%c%s%c%s.vacuum",
  242.  DataDir, SEP_CHAR, SEP_CHAR, dbname, SEP_CHAR, dbname);
  243. }
  244. else
  245. snprintf(filename, 256, "%s%c%s.vacuum", dbpath, SEP_CHAR, dbname);
  246. #ifndef __CYGWIN32__
  247. if ((fp = AllocateFile(filename, "r")) != NULL)
  248. #else
  249. if ((fp = AllocateFile(filename, "rb")) != NULL)
  250. #endif
  251. {
  252. fscanf(fp, "%d", &pid);
  253. FreeFile(fp);
  254. if (kill(pid, SIGKILLDAEMON1) < 0)
  255. {
  256. elog(ERROR, "can't kill vacuum daemon (pid %d) on '%s'",
  257.  pid, dbname);
  258. }
  259. }
  260. }