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

Commit 74686b6

Browse files
committed
Get rid of some unnecessary dependencies on DataDir: wherever possible,
the backend should rely on its working-directory setting instead. Also do some message-style police work in contrib/adminpack.
1 parent 62fe410 commit 74686b6

File tree

3 files changed

+83
-102
lines changed

3 files changed

+83
-102
lines changed

contrib/adminpack/adminpack.c

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Author: Andreas Pflug <pgadmin@pse-consulting.de>
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.7 2006/10/20 00:59:03 tgl Exp $
11+
* $PostgreSQL: pgsql/contrib/adminpack/adminpack.c,v 1.8 2006/11/06 03:06:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -60,43 +60,47 @@ typedef struct
6060
*/
6161

6262
/*
63-
* Return an absolute path. Argument may be absolute or
64-
* relative to the DataDir.
63+
* Convert a "text" filename argument to C string, and check it's allowable.
64+
*
65+
* Filename may be absolute or relative to the DataDir, but we only allow
66+
* absolute paths that match DataDir or Log_directory.
6567
*/
6668
static char *
67-
absClusterPath(text *arg, bool logAllowed)
69+
convert_and_check_filename(text *arg, bool logAllowed)
6870
{
69-
char *filename;
70-
int len = VARSIZE(arg) - VARHDRSZ;
71-
int dlen = strlen(DataDir);
71+
int input_len = VARSIZE(arg) - VARHDRSZ;
72+
char *filename = palloc(input_len + 1);
73+
74+
memcpy(filename, VARDATA(arg), input_len);
75+
filename[input_len] = '\0';
7276

73-
filename = palloc(len + 1);
74-
memcpy(filename, VARDATA(arg), len);
75-
filename[len] = 0;
77+
canonicalize_path(filename); /* filename can change length here */
7678

77-
if (strstr(filename, "..") != NULL)
79+
/* Disallow ".." in the path */
80+
if (path_contains_parent_reference(filename))
7881
ereport(ERROR,
7982
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
80-
(errmsg("No .. allowed in filenames"))));
83+
(errmsg("reference to parent directory (\"..\") not allowed"))));
8184

8285
if (is_absolute_path(filename))
8386
{
84-
if (logAllowed && !strncmp(filename, Log_directory, strlen(Log_directory)))
87+
/* Allow absolute references within DataDir */
88+
if (path_is_prefix_of_path(DataDir, filename))
89+
return filename;
90+
/* The log directory might be outside our datadir, but allow it */
91+
if (logAllowed &&
92+
is_absolute_path(Log_directory) &&
93+
path_is_prefix_of_path(Log_directory, filename))
8594
return filename;
86-
if (strncmp(filename, DataDir, dlen))
87-
ereport(ERROR,
88-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
89-
(errmsg("Absolute path not allowed"))));
9095

91-
return filename;
96+
ereport(ERROR,
97+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
98+
(errmsg("absolute path not allowed"))));
99+
return NULL; /* keep compiler quiet */
92100
}
93101
else
94102
{
95-
char *absname = palloc(dlen + len + 2);
96-
97-
sprintf(absname, "%s/%s", DataDir, filename);
98-
pfree(filename);
99-
return absname;
103+
return filename;
100104
}
101105
}
102106

@@ -129,29 +133,28 @@ pg_file_write(PG_FUNCTION_ARGS)
129133

130134
requireSuperuser();
131135

132-
filename = absClusterPath(PG_GETARG_TEXT_P(0), false);
136+
filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false);
133137
data = PG_GETARG_TEXT_P(1);
134138

135-
if (PG_ARGISNULL(2) || !PG_GETARG_BOOL(2))
139+
if (!PG_GETARG_BOOL(2))
136140
{
137141
struct stat fst;
138142

139143
if (stat(filename, &fst) >= 0)
140144
ereport(ERROR,
141145
(ERRCODE_DUPLICATE_FILE,
142-
errmsg("file %s exists", filename)));
146+
errmsg("file \"%s\" exists", filename)));
143147

144148
f = fopen(filename, "wb");
145149
}
146150
else
147151
f = fopen(filename, "ab");
148152

149153
if (!f)
150-
{
151154
ereport(ERROR,
152155
(errcode_for_file_access(),
153-
errmsg("could open file %s for writing: %m", filename)));
154-
}
156+
errmsg("could not open file \"%s\" for writing: %m",
157+
filename)));
155158

156159
if (VARSIZE(data) != 0)
157160
{
@@ -160,7 +163,7 @@ pg_file_write(PG_FUNCTION_ARGS)
160163
if (count != VARSIZE(data) - VARHDRSZ)
161164
ereport(ERROR,
162165
(errcode_for_file_access(),
163-
errmsg("error writing file %s: %m", filename)));
166+
errmsg("could not write file \"%s\": %m", filename)));
164167
}
165168
fclose(f);
166169

@@ -181,18 +184,18 @@ pg_file_rename(PG_FUNCTION_ARGS)
181184
if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
182185
PG_RETURN_NULL();
183186

184-
fn1 = absClusterPath(PG_GETARG_TEXT_P(0), false);
185-
fn2 = absClusterPath(PG_GETARG_TEXT_P(1), false);
187+
fn1 = convert_and_check_filename(PG_GETARG_TEXT_P(0), false);
188+
fn2 = convert_and_check_filename(PG_GETARG_TEXT_P(1), false);
186189
if (PG_ARGISNULL(2))
187190
fn3 = 0;
188191
else
189-
fn3 = absClusterPath(PG_GETARG_TEXT_P(2), false);
192+
fn3 = convert_and_check_filename(PG_GETARG_TEXT_P(2), false);
190193

191194
if (access(fn1, W_OK) < 0)
192195
{
193196
ereport(WARNING,
194197
(errcode_for_file_access(),
195-
errmsg("file %s not accessible: %m", fn1)));
198+
errmsg("file \"%s\" is not accessible: %m", fn1)));
196199

197200
PG_RETURN_BOOL(false);
198201
}
@@ -201,18 +204,18 @@ pg_file_rename(PG_FUNCTION_ARGS)
201204
{
202205
ereport(WARNING,
203206
(errcode_for_file_access(),
204-
errmsg("file %s not accessible: %m", fn2)));
207+
errmsg("file \"%s\" is not accessible: %m", fn2)));
205208

206209
PG_RETURN_BOOL(false);
207210
}
208211

209-
210212
rc = access(fn3 ? fn3 : fn2, 2);
211213
if (rc >= 0 || errno != ENOENT)
212214
{
213215
ereport(ERROR,
214216
(ERRCODE_DUPLICATE_FILE,
215-
errmsg("cannot rename to target file %s", fn3 ? fn3 : fn2)));
217+
errmsg("cannot rename to target file \"%s\"",
218+
fn3 ? fn3 : fn2)));
216219
}
217220

218221
if (fn3)
@@ -221,37 +224,37 @@ pg_file_rename(PG_FUNCTION_ARGS)
221224
{
222225
ereport(ERROR,
223226
(errcode_for_file_access(),
224-
errmsg("could not rename %s to %s: %m", fn2, fn3)));
227+
errmsg("could not rename \"%s\" to \"%s\": %m",
228+
fn2, fn3)));
225229
}
226230
if (rename(fn1, fn2) != 0)
227231
{
228232
ereport(WARNING,
229233
(errcode_for_file_access(),
230-
errmsg("could not rename %s to %s: %m", fn1, fn2)));
234+
errmsg("could not rename \"%s\" to \"%s\": %m",
235+
fn1, fn2)));
231236

232237
if (rename(fn3, fn2) != 0)
233238
{
234239
ereport(ERROR,
235240
(errcode_for_file_access(),
236-
errmsg("could not rename %s back to %s: %m", fn3, fn2)));
241+
errmsg("could not rename \"%s\" back to \"%s\": %m",
242+
fn3, fn2)));
237243
}
238244
else
239245
{
240246
ereport(ERROR,
241247
(ERRCODE_UNDEFINED_FILE,
242-
errmsg("renaming %s to %s was reverted", fn2, fn3)));
243-
248+
errmsg("renaming \"%s\" to \"%s\" was reverted",
249+
fn2, fn3)));
244250
}
245251
}
246252
}
247253
else if (rename(fn1, fn2) != 0)
248254
{
249-
ereport(WARNING,
250-
(errcode_for_file_access(),
251-
errmsg("renaming %s to %s %m", fn1, fn2)));
252255
ereport(ERROR,
253256
(errcode_for_file_access(),
254-
errmsg("could not rename %s to %s: %m", fn1, fn2)));
257+
errmsg("could not rename \"%s\" to \"%s\": %m", fn1, fn2)));
255258
}
256259

257260
PG_RETURN_BOOL(true);
@@ -265,7 +268,7 @@ pg_file_unlink(PG_FUNCTION_ARGS)
265268

266269
requireSuperuser();
267270

268-
filename = absClusterPath(PG_GETARG_TEXT_P(0), false);
271+
filename = convert_and_check_filename(PG_GETARG_TEXT_P(0), false);
269272

270273
if (access(filename, W_OK) < 0)
271274
{
@@ -274,15 +277,14 @@ pg_file_unlink(PG_FUNCTION_ARGS)
274277
else
275278
ereport(ERROR,
276279
(errcode_for_file_access(),
277-
errmsg("file %s not accessible: %m", filename)));
278-
280+
errmsg("file \"%s\" is not accessible: %m", filename)));
279281
}
280282

281283
if (unlink(filename) < 0)
282284
{
283285
ereport(WARNING,
284286
(errcode_for_file_access(),
285-
errmsg("could not unlink file %s: %m", filename)));
287+
errmsg("could not unlink file \"%s\": %m", filename)));
286288

287289
PG_RETURN_BOOL(false);
288290
}
@@ -316,13 +318,7 @@ pg_logdir_ls(PG_FUNCTION_ARGS)
316318
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
317319

318320
fctx = palloc(sizeof(directory_fctx));
319-
if (is_absolute_path(Log_directory))
320-
fctx->location = pstrdup(Log_directory);
321-
else
322-
{
323-
fctx->location = palloc(strlen(DataDir) + strlen(Log_directory) + 2);
324-
sprintf(fctx->location, "%s/%s", DataDir, Log_directory);
325-
}
321+
326322
tupdesc = CreateTemplateTupleDesc(2, false);
327323
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
328324
TIMESTAMPOID, -1, 0);
@@ -331,12 +327,14 @@ pg_logdir_ls(PG_FUNCTION_ARGS)
331327

332328
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
333329

330+
fctx->location = pstrdup(Log_directory);
334331
fctx->dirdesc = AllocateDir(fctx->location);
335332

336333
if (!fctx->dirdesc)
337334
ereport(ERROR,
338335
(errcode_for_file_access(),
339-
errmsg("%s is not browsable: %m", fctx->location)));
336+
errmsg("could not read directory \"%s\": %m",
337+
fctx->location)));
340338

341339
funcctx->user_fctx = fctx;
342340
MemoryContextSwitchTo(oldcontext);

0 commit comments

Comments
 (0)