Skip to content

Commit b8e5581

Browse files
committed
Fix rmtree() so that it keeps going after failure to remove any individual
file; the idea is that we should clean up as much as we can, even if there's some problem removing one file. Make the error messages a bit less misleading, too. In passing, const-ify function arguments.
1 parent 9cb91f9 commit b8e5581

File tree

3 files changed

+53
-38
lines changed

3 files changed

+53
-38
lines changed

src/backend/commands/dbcommands.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.207 2008/04/18 06:48:38 heikki Exp $
16+
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.208 2008/04/18 17:05:45 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1321,7 +1321,7 @@ remove_dbtablespaces(Oid db_id)
13211321

13221322
if (!rmtree(dstpath, true))
13231323
ereport(WARNING,
1324-
(errmsg("could not remove database directory \"%s\"",
1324+
(errmsg("some useless files may be left behind in old database directory \"%s\"",
13251325
dstpath)));
13261326

13271327
/* Record the filesystem change in XLOG */
@@ -1490,7 +1490,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
14901490
{
14911491
if (!rmtree(dst_path, true))
14921492
ereport(WARNING,
1493-
(errmsg("could not remove database directory \"%s\"",
1493+
(errmsg("some useless files may be left behind in old database directory \"%s\"",
14941494
dst_path)));
14951495
}
14961496

@@ -1529,7 +1529,7 @@ dbase_redo(XLogRecPtr lsn, XLogRecord *record)
15291529
/* And remove the physical files */
15301530
if (!rmtree(dst_path, true))
15311531
ereport(WARNING,
1532-
(errmsg("could not remove database directory \"%s\"",
1532+
(errmsg("some useless files may be left behind in old database directory \"%s\"",
15331533
dst_path)));
15341534
}
15351535
else

src/include/port.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/port.h,v 1.121 2008/04/16 14:19:56 adunstan Exp $
9+
* $PostgreSQL: pgsql/src/include/port.h,v 1.122 2008/04/18 17:05:45 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -48,7 +48,7 @@ extern bool get_home_path(char *ret_path);
4848
extern void get_parent_directory(char *path);
4949

5050
/* port/dirmod.c */
51-
extern char **pgfnames(char *path);
51+
extern char **pgfnames(const char *path);
5252
extern void pgfnames_cleanup(char **filenames);
5353

5454
/*
@@ -279,7 +279,7 @@ extern int pgsymlink(const char *oldpath, const char *newpath);
279279

280280
extern void copydir(char *fromdir, char *todir, bool recurse);
281281

282-
extern bool rmtree(char *path, bool rmtopdir);
282+
extern bool rmtree(const char *path, bool rmtopdir);
283283

284284
/*
285285
* stat() is not guaranteed to set the st_size field on win32, so we

src/port/dirmod.c

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.54 2008/04/18 06:48:38 heikki Exp $
13+
* $PostgreSQL: pgsql/src/port/dirmod.c,v 1.55 2008/04/18 17:05:45 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -291,8 +291,8 @@ pgsymlink(const char *oldpath, const char *newpath)
291291
* must call pgfnames_cleanup later to free the memory allocated by this
292292
* function.
293293
*/
294-
char **
295-
pgfnames(char *path)
294+
char **
295+
pgfnames(const char *path)
296296
{
297297
DIR *dir;
298298
struct dirent *file;
@@ -380,12 +380,15 @@ pgfnames_cleanup(char **filenames)
380380
* Assumes path points to a valid directory.
381381
* Deletes everything under path.
382382
* If rmtopdir is true deletes the directory too.
383+
* Returns true if successful, false if there was any problem.
384+
* (The details of the problem are reported already, so caller
385+
* doesn't really have to say anything more, but most do.)
383386
*/
384387
bool
385-
rmtree(char *path, bool rmtopdir)
388+
rmtree(const char *path, bool rmtopdir)
386389
{
390+
bool result = true;
387391
char pathbuf[MAXPGPATH];
388-
char *filepath;
389392
char **filenames;
390393
char **filename;
391394
struct stat statbuf;
@@ -400,11 +403,9 @@ rmtree(char *path, bool rmtopdir)
400403
return false;
401404

402405
/* now we have the names we can start removing things */
403-
filepath = pathbuf;
404-
405406
for (filename = filenames; *filename; filename++)
406407
{
407-
snprintf(filepath, MAXPGPATH, "%s/%s", path, *filename);
408+
snprintf(pathbuf, MAXPGPATH, "%s/%s", path, *filename);
408409

409410
/*
410411
* It's ok if the file is not there anymore; we were just about to
@@ -417,54 +418,68 @@ rmtree(char *path, bool rmtopdir)
417418
* requests, but because that's asynchronous, it's not guaranteed
418419
* that the bgwriter receives the message in time.
419420
*/
420-
if (lstat(filepath, &statbuf) != 0)
421+
if (lstat(pathbuf, &statbuf) != 0)
421422
{
422423
if (errno != ENOENT)
423-
goto report_and_fail;
424-
else
425-
continue;
424+
{
425+
#ifndef FRONTEND
426+
elog(WARNING, "could not stat file or directory \"%s\": %m",
427+
pathbuf);
428+
#else
429+
fprintf(stderr, _("could not stat file or directory \"%s\": %s\n"),
430+
pathbuf, strerror(errno));
431+
#endif
432+
result = false;
433+
}
434+
continue;
426435
}
427436

428437
if (S_ISDIR(statbuf.st_mode))
429438
{
430439
/* call ourselves recursively for a directory */
431-
if (!rmtree(filepath, true))
440+
if (!rmtree(pathbuf, true))
432441
{
433442
/* we already reported the error */
434-
pgfnames_cleanup(filenames);
435-
return false;
443+
result = false;
436444
}
437445
}
438446
else
439447
{
440-
if (unlink(filepath) != 0)
448+
if (unlink(pathbuf) != 0)
441449
{
442450
if (errno != ENOENT)
443-
goto report_and_fail;
451+
{
452+
#ifndef FRONTEND
453+
elog(WARNING, "could not remove file or directory \"%s\": %m",
454+
pathbuf);
455+
#else
456+
fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
457+
pathbuf, strerror(errno));
458+
#endif
459+
result = false;
460+
}
444461
}
445462
}
446463
}
447464

448465
if (rmtopdir)
449466
{
450-
filepath = path;
451-
if (rmdir(filepath) != 0)
452-
goto report_and_fail;
453-
}
454-
455-
pgfnames_cleanup(filenames);
456-
return true;
457-
458-
report_and_fail:
459-
467+
if (rmdir(path) != 0)
468+
{
460469
#ifndef FRONTEND
461-
elog(WARNING, "could not remove file or directory \"%s\": %m", filepath);
470+
elog(WARNING, "could not remove file or directory \"%s\": %m",
471+
path);
462472
#else
463-
fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
464-
filepath, strerror(errno));
473+
fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
474+
path, strerror(errno));
465475
#endif
476+
result = false;
477+
}
478+
}
479+
466480
pgfnames_cleanup(filenames);
467-
return false;
481+
482+
return result;
468483
}
469484

470485

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy