Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3304341

Browse files
committed
Reimplement alternative database locations with symlinks. No changes in
user interface.
1 parent 218f357 commit 3304341

File tree

3 files changed

+113
-94
lines changed

3 files changed

+113
-94
lines changed

src/backend/commands/dbcommands.c

+109-90
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.63 2000/10/28 16:20:54 vadim Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.64 2000/11/08 16:59:49 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -17,8 +17,6 @@
1717

1818
#include <errno.h>
1919
#include <fcntl.h>
20-
#include <stdlib.h>
21-
#include <string.h>
2220
#include <unistd.h>
2321
#include <sys/stat.h>
2422
#include <sys/types.h>
@@ -37,12 +35,10 @@
3735

3836

3937
/* non-export function prototypes */
40-
static bool
41-
get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb);
42-
43-
static bool
44-
get_db_info(const char *name, char *dbpath, Oid *dbIdP, int4 *ownerIdP);
45-
38+
static bool get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb);
39+
static bool get_db_info(const char *name, char *dbpath, Oid *dbIdP, int4 *ownerIdP);
40+
static char * resolve_alt_dbpath(const char * dbpath, Oid dboid);
41+
static bool remove_dbdirs(const char * real_loc, const char * altloc);
4642

4743
/*
4844
* CREATE DATABASE
@@ -52,8 +48,8 @@ void
5248
createdb(const char *dbname, const char *dbpath, int encoding)
5349
{
5450
char buf[2 * MAXPGPATH + 100];
55-
char *loc;
56-
char locbuf[512];
51+
char *altloc;
52+
char *real_loc;
5753
int ret;
5854
bool use_super,
5955
use_createdb;
@@ -77,24 +73,6 @@ createdb(const char *dbname, const char *dbpath, int encoding)
7773
if (IsTransactionBlock())
7874
elog(ERROR, "CREATE DATABASE: may not be called in a transaction block");
7975

80-
#ifdef OLD_FILE_NAMING
81-
/* Generate directory name for the new database */
82-
if (dbpath == NULL || strcmp(dbpath, dbname) == 0)
83-
strcpy(locbuf, dbname);
84-
else
85-
snprintf(locbuf, sizeof(locbuf), "%s/%s", dbpath, dbname);
86-
87-
loc = ExpandDatabasePath(locbuf);
88-
89-
if (loc == NULL)
90-
elog(ERROR,
91-
"The database path '%s' is invalid. "
92-
"This may be due to a character that is not allowed or because the chosen "
93-
"path isn't permitted for databases", dbpath);
94-
#else
95-
locbuf[0] = 0; /* Avoid junk in strings */
96-
#endif
97-
9876
/*
9977
* Insert a new tuple into pg_database
10078
*/
@@ -108,13 +86,15 @@ createdb(const char *dbname, const char *dbpath, int encoding)
10886
dboid = newoid();
10987

11088
/* Form tuple */
111-
new_record[Anum_pg_database_datname - 1] = DirectFunctionCall1(namein,
112-
CStringGetDatum(dbname));
89+
new_record[Anum_pg_database_datname - 1] =
90+
DirectFunctionCall1(namein, CStringGetDatum(dbname));
11391
new_record[Anum_pg_database_datdba - 1] = Int32GetDatum(GetUserId());
11492
new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
115-
new_record[Anum_pg_database_datlastsysoid - 1] = ObjectIdGetDatum(dboid); /* Save current OID val */
116-
new_record[Anum_pg_database_datpath - 1] = DirectFunctionCall1(textin,
117-
CStringGetDatum(locbuf));
93+
/* Save current OID val */
94+
new_record[Anum_pg_database_datlastsysoid - 1] = ObjectIdGetDatum(dboid);
95+
/* no nulls here, GetRawDatabaseInfo doesn't like them */
96+
new_record[Anum_pg_database_datpath - 1] =
97+
DirectFunctionCall1(textin, CStringGetDatum(dbpath ? dbpath : ""));
11898

11999
tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls);
120100

@@ -126,9 +106,12 @@ createdb(const char *dbname, const char *dbpath, int encoding)
126106
*/
127107
heap_insert(pg_database_rel, tuple);
128108

129-
#ifndef OLD_FILE_NAMING
130-
loc = GetDatabasePath(tuple->t_data->t_oid);
131-
#endif
109+
real_loc = GetDatabasePath(tuple->t_data->t_oid);
110+
altloc = resolve_alt_dbpath(dbpath, tuple->t_data->t_oid);
111+
112+
if (strchr(real_loc, '\'') && strchr(altloc, '\''))
113+
elog(ERROR, "database path may not contain single quotes");
114+
/* ... otherwise we'd be open to shell exploits below */
132115

133116
/*
134117
* Update indexes (there aren't any currently)
@@ -156,41 +139,28 @@ createdb(const char *dbname, const char *dbpath, int encoding)
156139

157140
/* Copy the template database to the new location */
158141

159-
if (mkdir(loc, S_IRWXU) != 0)
160-
elog(ERROR, "CREATE DATABASE: unable to create database directory '%s': %s", loc, strerror(errno));
142+
if (mkdir((altloc ? altloc : real_loc), S_IRWXU) != 0)
143+
elog(ERROR, "CREATE DATABASE: unable to create database directory '%s': %s",
144+
(altloc ? altloc : real_loc), strerror(errno));
161145

162-
#ifdef OLD_FILE_NAMING
163-
snprintf(buf, sizeof(buf), "cp %s%cbase%ctemplate1%c* '%s'",
164-
DataDir, SEP_CHAR, SEP_CHAR, SEP_CHAR, loc);
165-
#else
146+
if (altloc)
166147
{
167-
char *tmpl = GetDatabasePath(TemplateDbOid);
168-
169-
snprintf(buf, sizeof(buf), "cp %s%c* '%s'",
170-
tmpl, SEP_CHAR, loc);
171-
pfree(tmpl);
148+
if (symlink(altloc, real_loc) != 0)
149+
elog(ERROR, "CREATE DATABASE: could not link %s to %s: %s",
150+
real_loc, altloc, strerror(errno));
172151
}
173-
#endif
152+
153+
snprintf(buf, sizeof(buf), "cp '%s'/* '%s'",
154+
GetDatabasePath(TemplateDbOid), real_loc);
174155

175156
ret = system(buf);
176157
/* Some versions of SunOS seem to return ECHILD after a system() call */
177-
#if defined(sun)
178158
if (ret != 0 && errno != ECHILD)
179-
#else
180-
if (ret != 0)
181-
#endif
182159
{
183-
/* Failed, so try to clean up the created directory ... */
184-
snprintf(buf, sizeof(buf), "rm -rf '%s'", loc);
185-
ret = system(buf);
186-
#if defined(sun)
187-
if (ret == 0 || errno == ECHILD)
188-
#else
189-
if (ret == 0)
190-
#endif
160+
if (remove_dbdirs(real_loc, altloc))
191161
elog(ERROR, "CREATE DATABASE: could not initialize database directory");
192162
else
193-
elog(ERROR, "CREATE DATABASE: Could not initialize database directory. Delete failed as well");
163+
elog(ERROR, "CREATE DATABASE: could not initialize database directory; delete failed as well");
194164
}
195165

196166
#ifdef XLOG
@@ -210,9 +180,9 @@ dropdb(const char *dbname)
210180
int4 db_owner;
211181
bool use_super;
212182
Oid db_id;
213-
char *path,
214-
dbpath[MAXPGPATH],
215-
buf[MAXPGPATH + 100];
183+
char *altloc;
184+
char *real_loc;
185+
char dbpath[MAXPGPATH];
216186
Relation pgdbrel;
217187
HeapScanDesc pgdbscan;
218188
ScanKeyData key;
@@ -221,33 +191,25 @@ dropdb(const char *dbname)
221191
AssertArg(dbname);
222192

223193
if (strcmp(dbname, "template1") == 0)
224-
elog(ERROR, "DROP DATABASE: May not be executed on the template1 database");
194+
elog(ERROR, "DROP DATABASE: may not be executed on the template1 database");
225195

226196
if (strcmp(dbname, DatabaseName) == 0)
227-
elog(ERROR, "DROP DATABASE: Cannot be executed on the currently open database");
197+
elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database");
228198

229199
if (IsTransactionBlock())
230-
elog(ERROR, "DROP DATABASE: May not be called in a transaction block");
200+
elog(ERROR, "DROP DATABASE: may not be called in a transaction block");
231201

232202
if (!get_user_info(GetUserId(), &use_super, NULL))
233-
elog(ERROR, "Current user name is invalid");
203+
elog(ERROR, "current user name is invalid");
234204

235205
if (!get_db_info(dbname, dbpath, &db_id, &db_owner))
236-
elog(ERROR, "DROP DATABASE: Database \"%s\" does not exist", dbname);
206+
elog(ERROR, "DROP DATABASE: database \"%s\" does not exist", dbname);
237207

238208
if (GetUserId() != db_owner && !use_super)
239-
elog(ERROR, "DROP DATABASE: Permission denied");
240-
241-
#ifdef OLD_FILE_NAMING
242-
path = ExpandDatabasePath(dbpath);
243-
if (path == NULL)
244-
elog(ERROR,
245-
"The database path '%s' is invalid. "
246-
"This may be due to a character that is not allowed or because the chosen "
247-
"path isn't permitted for databases", path);
248-
#else
249-
path = GetDatabasePath(db_id);
250-
#endif
209+
elog(ERROR, "DROP DATABASE: permission denied");
210+
211+
real_loc = GetDatabasePath(db_id);
212+
altloc = resolve_alt_dbpath(dbpath, db_id);
251213

252214
/*
253215
* Obtain exclusive lock on pg_database. We need this to ensure that
@@ -266,7 +228,7 @@ dropdb(const char *dbname)
266228
if (DatabaseHasActiveBackends(db_id))
267229
{
268230
heap_close(pgdbrel, AccessExclusiveLock);
269-
elog(ERROR, "DROP DATABASE: Database \"%s\" is being accessed by other users", dbname);
231+
elog(ERROR, "DROP DATABASE: database \"%s\" is being accessed by other users", dbname);
270232
}
271233

272234
/*
@@ -320,13 +282,7 @@ dropdb(const char *dbname)
320282
/*
321283
* Remove the database's subdirectory and everything in it.
322284
*/
323-
snprintf(buf, sizeof(buf), "rm -rf '%s'", path);
324-
#if defined(sun)
325-
if (system(buf) != 0 && errno != ECHILD)
326-
#else
327-
if (system(buf) != 0)
328-
#endif
329-
elog(NOTICE, "DROP DATABASE: The database directory '%s' could not be removed", path);
285+
remove_dbdirs(real_loc, altloc);
330286
}
331287

332288

@@ -426,3 +382,66 @@ get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb)
426382

427383
return true;
428384
}
385+
386+
387+
static char *
388+
resolve_alt_dbpath(const char * dbpath, Oid dboid)
389+
{
390+
char * prefix;
391+
char * ret;
392+
size_t len;
393+
394+
if (dbpath == NULL || dbpath[0] == '\0')
395+
return NULL;
396+
397+
if (strchr(dbpath, '/'))
398+
{
399+
#ifdef ALLOW_ABSOLUTE_DBPATHS
400+
prefix = dbpath;
401+
#else
402+
elog(ERROR, "Absolute paths are not allowed as database locations");
403+
#endif
404+
}
405+
else
406+
{
407+
/* must be environment variable */
408+
char * var = getenv(dbpath);
409+
if (!var)
410+
elog(ERROR, "environment variable %s not set", dbpath);
411+
if (var[0] != '/')
412+
elog(ERROR, "environment variable %s must be absolute path", dbpath);
413+
prefix = var;
414+
}
415+
416+
len = strlen(prefix) + 6 + sizeof(Oid) * 8 + 1;
417+
ret = palloc(len);
418+
snprintf(ret, len, "%s/base/%u", prefix, dboid);
419+
420+
return ret;
421+
}
422+
423+
424+
static bool
425+
remove_dbdirs(const char * real_loc, const char * altloc)
426+
{
427+
char buf[MAXPGPATH + 100];
428+
bool success = true;
429+
430+
if (altloc)
431+
/* remove symlink */
432+
if (unlink(real_loc) != 0)
433+
{
434+
elog(NOTICE, "could not remove '%s': %s", real_loc, strerror(errno));
435+
success = false;
436+
}
437+
438+
snprintf(buf, sizeof(buf), "rm -rf '%s'", altloc ? altloc : real_loc);
439+
if (system(buf) != 0 && errno != ECHILD)
440+
{
441+
elog(NOTICE, "database directory '%s' could not be removed",
442+
altloc ? altloc : real_loc);
443+
success = false;
444+
}
445+
446+
return success;
447+
}

src/include/catalog/catversion.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $Id: catversion.h,v 1.55 2000/11/06 15:58:46 thomas Exp $
40+
* $Id: catversion.h,v 1.56 2000/11/08 16:59:50 petere Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200011060
56+
#define CATALOG_VERSION_NO 200011080
5757

5858
#endif

src/include/catalog/pg_database.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $Id: pg_database.h,v 1.13 2000/10/22 18:29:58 tgl Exp $
11+
* $Id: pg_database.h,v 1.14 2000/11/08 16:59:50 petere Exp $
1212
*
1313
* NOTES
1414
* the genbki.sh script reads this file and generates .bki
@@ -58,7 +58,7 @@ typedef FormData_pg_database *Form_pg_database;
5858
#define Anum_pg_database_datlastsysoid 4
5959
#define Anum_pg_database_datpath 5
6060

61-
DATA(insert OID = 1 ( template1 PGUID ENCODING 0 template1 ));
61+
DATA(insert OID = 1 ( template1 PGUID ENCODING 0 "" ));
6262
DESCR("");
6363

6464
#define TemplateDbOid 1

0 commit comments

Comments
 (0)