home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / parser / dbcommands.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  8.3 KB  |  323 lines

  1. #include <stdio.h>
  2.  
  3. #include "tmp/postgres.h"
  4.  
  5. RcsId("$Header: /private/postgres/src/parser/RCS/dbcommands.c,v 1.11 1992/06/28 03:46:48 mao Exp $");
  6.  
  7. #include "access/heapam.h"
  8. #include "access/htup.h"
  9. #include "access/relscan.h"
  10. #include "utils/rel.h"
  11. #include "utils/log.h"
  12. #include "tmp/daemon.h"
  13. #include "catalog/pg_proc.h"
  14. #include "catalog/pg_user.h"
  15. #include "catalog/pg_database.h"
  16.  
  17.  
  18. extern int NStriping;
  19. extern char *PostgresHomes[];
  20. extern char *GetDataHome();
  21. extern char *PG_username;
  22. extern char *DBName;
  23.  
  24. createdb(dbname)
  25.     char *dbname;
  26. {
  27.     ObjectId db_id, user_id;
  28.     char *path;
  29.     char buf[512];
  30.     int i;
  31.  
  32.     /*
  33.      *  If this call returns, the database does not exist and we're allowed
  34.      *  to create databases.
  35.      */
  36.     check_permissions("createdb", dbname, &db_id, &user_id);
  37.  
  38.     /* close virtual file descriptors so we can do system() calls */
  39.     closeAllVfds();
  40.  
  41.     if (NStriping == 0) {
  42.     path = GetDataHome();
  43.     sprintf(buf, "mkdir %s/data/base/%s", path, dbname);
  44.     system(buf);
  45.     sprintf(buf, "cp %s/data/base/template1/* %s/data/base/%s",
  46.                     path, path, dbname);
  47.     system(buf);
  48.     } else {
  49.     for (i = 0; i < NStriping; i++)
  50.     {
  51.         path = PostgresHomes[i];
  52.         sprintf(buf, "mkdir %s/data/base/%s", path, dbname);
  53.         system(buf);
  54.         sprintf(buf, "cp %s/data/base/template1/* %s/data/base/%s",
  55.             path, path, dbname);
  56.         system(buf);
  57.     }
  58.     }
  59.  
  60.     sprintf(buf, "append pg_database (datname = \"%s\"::char16, \
  61.                   datdba = \"%d\"::oid, datpath = \"%s\"::text)",
  62.           dbname, user_id, dbname);
  63.     pg_eval(buf, (char *) NULL, (ObjectId *) NULL, 0);
  64. }
  65.  
  66. destroydb(dbname)
  67.     char *dbname;
  68. {
  69.     ObjectId user_id, db_id;
  70.     char *path;
  71.     int i;
  72.     char buf[512];
  73.  
  74.     /*
  75.      *  If this call returns, the database exists and we're allowed to
  76.      *  remove it.
  77.      */
  78.     check_permissions("destroydb", dbname, &db_id, &user_id);
  79.  
  80.     if (!ObjectIdIsValid(db_id)) {
  81.     elog(FATAL, "impossible: pg_database instance with invalid OID.");
  82.     }
  83.  
  84.     /* stop the vacuum daemon */
  85.     stop_vacuum(dbname);
  86.  
  87.     /* remove the data directory */
  88.     if (NStriping == 0) {
  89.     path = GetDataHome();
  90.     sprintf(buf, "rm -r %s/data/base/%s", path, dbname);
  91.     system(buf);
  92.     } else {
  93.     for (i = 0; i < NStriping; i++) {
  94.         path = PostgresHomes[i];
  95.         sprintf(buf, "rm -r %s/data/base/%s", path, dbname);
  96.         system(buf);
  97.     }
  98.     }
  99.  
  100.     /* remove the pg_database tuple */
  101.     sprintf(buf, "delete pg_database where pg_database.oid = \"%d\"::oid",
  102.           db_id);
  103.     pg_eval(buf, (char *) NULL, (ObjectId *) NULL, 0);
  104.  
  105.     /* drop pages for this database that are in the shared buffer cache */
  106.     DropBuffers(db_id);
  107. }
  108.  
  109. HeapTuple
  110. get_pg_usertup(command, username)
  111.     char *command;
  112.     char *username;
  113. {
  114.     Relation urel;
  115.     HeapTuple usertup;
  116.     HeapTuple tup;
  117.     Buffer buf;
  118.     HeapScanDesc scan;
  119.     ScanKeyData scanKey;
  120.  
  121.     urel = heap_openr(Name_pg_user);
  122.     if (!RelationIsValid(urel))
  123.     elog(FATAL, "%s: cannot open %s.", command, Name_pg_user);
  124.  
  125.     ScanKeyEntryInitialize(&scanKey.data[0], 0,
  126.                            Anum_pg_user_usename,
  127.                            NameEqualRegProcedure, NameGetDatum(username));
  128.  
  129.     scan = heap_beginscan(urel, 0, NowTimeQual, 1, &scanKey);
  130.     if (!HeapScanIsValid(scan))
  131.     elog(WARN, "%s: cannot begin scan of pg_user.", command);
  132.  
  133.     /*
  134.      *  since we want to return the tuple out of this proc, and we're
  135.      *  going to close the relation, copy the tuple and return the copy.
  136.      */
  137.     tup = heap_getnext(scan, 0, &buf);
  138.  
  139.     if (HeapTupleIsValid(tup)) {
  140.     usertup = (HeapTuple) palloctup(tup, buf, urel);
  141.     ReleaseBuffer(buf);
  142.     } else {
  143.     elog(WARN, "No pg_user tuple for %s", username);
  144.     }
  145.  
  146.     heap_endscan(scan);
  147.     heap_close(urel);
  148.     return (usertup);
  149. }
  150.  
  151. HeapTuple
  152. get_pg_dbtup(command, dbname, dbrel)
  153.     char *command;
  154.     char *dbname;
  155.     Relation dbrel;
  156. {
  157.     HeapTuple dbtup;
  158.     HeapTuple tup;
  159.     Buffer buf;
  160.     HeapScanDesc scan;
  161.     ScanKeyData scanKey;
  162.  
  163.     ScanKeyEntryInitialize(&scanKey.data[0], 0, Anum_pg_database_datname,
  164.                 NameEqualRegProcedure, NameGetDatum(dbname));
  165.  
  166.     scan = heap_beginscan(dbrel, 0, NowTimeQual, 1, &scanKey);
  167.     if (!HeapScanIsValid(scan))
  168.     elog(WARN, "%s: cannot begin scan of pg_database.", command);
  169.  
  170.     /*
  171.      *  since we want to return the tuple out of this proc, and we're
  172.      *  going to close the relation, copy the tuple and return the copy.
  173.      */
  174.     tup = heap_getnext(scan, 0, &buf);
  175.  
  176.     if (HeapTupleIsValid(tup)) {
  177.     dbtup = (HeapTuple) palloctup(tup, buf, dbrel);
  178.     ReleaseBuffer(buf);
  179.     } else
  180.     dbtup = tup;
  181.  
  182.     heap_endscan(scan);
  183.     return (dbtup);
  184. }
  185.  
  186. /*
  187.  *  check_permissions() -- verify that the user is permitted to do this.
  188.  *
  189.  *  If the user is not allowed to carry out this operation, this routine
  190.  *  elog(WARN, ...)s, which will abort the xact.  As a side effect, the
  191.  *  user's pg_user tuple OID is returned in userIdP and the target database's
  192.  *  OID is returned in dbIdP.
  193.  */
  194.  
  195. check_permissions(command, dbname, dbIdP, userIdP)
  196.     char *command;
  197.     char *dbname;
  198.     ObjectId *dbIdP;
  199.     ObjectId *userIdP;
  200. {
  201.     Relation urel, dbrel;
  202.     HeapTuple dbtup, utup;
  203.     ObjectId dbowner;
  204.     ObjectId dbid;
  205.     char use_createdb;
  206.     bool dbfound;
  207.     bool use_super;
  208.  
  209.     utup = get_pg_usertup(command, PG_username);
  210.     *userIdP = ((Form_pg_user)GETSTRUCT(utup))->usesysid;
  211.     use_super = ((Form_pg_user)GETSTRUCT(utup))->usesuper;
  212.     use_createdb = ((Form_pg_user)GETSTRUCT(utup))->usecreatedb;
  213.  
  214.     /* Check to make sure user has permission to use createdb */
  215.     if (!use_createdb) {
  216.         elog(WARN, "User %s is not allowed to create/destroy databases",
  217.              PG_username);
  218.     }
  219.  
  220.     /* Make sure we are not mucking with the template database */
  221.     if (!strcmp(dbname, "template1")) {
  222.         elog(WARN, "%s cannot be executed on the template database.", command);
  223.     }
  224.  
  225.     /* Check to make sure database is not the currently open database */
  226.     if (!strcmp(dbname, DBName)) {
  227.         elog(WARN, "%s cannot be executed on an open database", command);
  228.     }
  229.  
  230.     /* Check to make sure database is owned by this user */
  231.  
  232.     /* 
  233.      * need the reldesc to get the database owner out of dbtup 
  234.      * and to set a write lock on it.
  235.      */
  236.     dbrel = heap_openr(Name_pg_database);
  237.  
  238.     if (!RelationIsValid(dbrel))
  239.     elog(FATAL, "%s: cannot open %s.", command, Name_pg_database);
  240.  
  241.     /*
  242.      * Acquire a write lock on pg_database from the beginning to avoid 
  243.      * upgrading a read lock to a write lock.  Upgrading causes long delays 
  244.      * when multiple 'createdb's or 'destroydb's are run simult. -mer 7/3/91
  245.      */
  246.     RelationSetLockForWrite(dbrel);
  247.     dbtup = get_pg_dbtup(command, dbname, dbrel);
  248.     dbfound = HeapTupleIsValid(dbtup);
  249.  
  250.     if (dbfound) {
  251.     dbowner = (ObjectId) heap_getattr(dbtup, InvalidBuffer,
  252.                           Anum_pg_database_datdba,
  253.                           &(dbrel->rd_att),
  254.                           (char *) NULL);
  255.     *dbIdP = dbtup->t_oid;
  256.     } else {
  257.     *dbIdP = InvalidObjectId;
  258.     }
  259.  
  260.     heap_close(dbrel);
  261.  
  262.     /*
  263.      *  Now be sure that the user is allowed to do this.
  264.      */
  265.  
  266.     if (dbfound && !strcmp(command, "createdb")) {
  267.  
  268.         elog(WARN, "createdb: database %s already exists.", dbname);
  269.  
  270.     } else if (!dbfound && !strcmp(command, "destroydb")) {
  271.  
  272.         elog(WARN, "destroydb: database %s does not exist.", dbname);
  273.  
  274.     } else if (dbfound && !strcmp(command, "destroydb")
  275.            && dbowner != *userIdP && use_super == false) {
  276.  
  277.         elog(WARN, "%s: database %s is not owned by you.", command, dbname);
  278.  
  279.     }
  280. }
  281.  
  282. /*
  283.  *  stop_vacuum() -- stop the vacuum daemon on the database, if one is
  284.  *             running.
  285.  */
  286. stop_vacuum(dbname)
  287.     char *dbname;
  288. {
  289.     int i;
  290.     char *path;
  291.     char buf[512];
  292.     char filename[256];
  293.     FILE *fp;
  294.     int pid;
  295.  
  296.     if (NStriping == 0) {
  297.     path = GetDataHome();
  298.     sprintf(filename, "%s/data/base/%s/%s.vacuum", path, dbname, dbname);
  299.     if ((fp = fopen(filename, "r")) != (FILE *) NULL) {
  300.         fscanf(fp, "%d", &pid);
  301.         fclose(fp);
  302.         if (kill(pid, SIGKILLDAEMON1) < 0) {
  303.         elog(WARN, "can't kill vacuum daemon (pid %d) on %s",
  304.                pid, dbname);
  305.         }
  306.     }
  307.     } else {
  308.     for (i = 0; i < NStriping; i++) {
  309.         path = PostgresHomes[i];
  310.         sprintf(filename, "%s/data/base/%s/%s.vacuum",
  311.              path, dbname, dbname);
  312.         if ((fp = fopen(filename, "r")) != (FILE *) NULL) {
  313.         fscanf(fp, "%d", &pid);
  314.         fclose(fp);
  315.         if (kill(pid, SIGKILLDAEMON1) < 0) {
  316.             elog(WARN, "can't kill vacuum daemon (pid %d) on %s",
  317.                    pid, dbname);
  318.         }
  319.         }
  320.     }
  321.     }
  322. }
  323.