From 2e6bc4b806ca92433932b34c019293a201f03e11 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sat, 19 Oct 2013 10:20:51 -0400 Subject: [PATCH] Move rmtree() from libpgport to libpgcommon It requires pgfnames() from libpgcommon. --- src/bin/initdb/nls.mk | 2 +- src/common/Makefile | 2 +- src/common/rmtree.c | 131 ++++++++++++++++++++++++++++++++++++ src/port/dirmod.c | 110 ------------------------------ src/tools/msvc/Mkvcbuild.pm | 2 +- 5 files changed, 134 insertions(+), 113 deletions(-) create mode 100644 src/common/rmtree.c diff --git a/src/bin/initdb/nls.mk b/src/bin/initdb/nls.mk index 8febf18440..377e75970b 100644 --- a/src/bin/initdb/nls.mk +++ b/src/bin/initdb/nls.mk @@ -1,5 +1,5 @@ # src/bin/initdb/nls.mk CATALOG_NAME = initdb AVAIL_LANGUAGES = cs de es fr it ja pl pt_BR ru zh_CN -GETTEXT_FILES = findtimezone.c initdb.c ../../common/exec.c ../../common/fe_memutils.c ../../common/pgfnames.c ../../common/wait_error.c ../../port/dirmod.c +GETTEXT_FILES = findtimezone.c initdb.c ../../common/exec.c ../../common/fe_memutils.c ../../common/pgfnames.c ../../common/rmtree.c ../../common/wait_error.c ../../port/dirmod.c GETTEXT_TRIGGERS = simple_prompt diff --git a/src/common/Makefile b/src/common/Makefile index 575a48a94d..d4ef2f1a30 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -23,7 +23,7 @@ include $(top_builddir)/src/Makefile.global override CPPFLAGS := -DFRONTEND $(CPPFLAGS) LIBS += $(PTHREAD_LIBS) -OBJS_COMMON = exec.o pgfnames.o relpath.o wait_error.o +OBJS_COMMON = exec.o pgfnames.o relpath.o rmtree.o wait_error.o OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o diff --git a/src/common/rmtree.c b/src/common/rmtree.c new file mode 100644 index 0000000000..ec7bce8e6d --- /dev/null +++ b/src/common/rmtree.c @@ -0,0 +1,131 @@ +/*------------------------------------------------------------------------- + * + * rmtree.c + * + * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/common/rmtree.c + * + *------------------------------------------------------------------------- + */ + +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif + +#include +#include + + +/* + * rmtree + * + * Delete a directory tree recursively. + * Assumes path points to a valid directory. + * Deletes everything under path. + * If rmtopdir is true deletes the directory too. + * Returns true if successful, false if there was any problem. + * (The details of the problem are reported already, so caller + * doesn't really have to say anything more, but most do.) + */ +bool +rmtree(const char *path, bool rmtopdir) +{ + bool result = true; + char pathbuf[MAXPGPATH]; + char **filenames; + char **filename; + struct stat statbuf; + + /* + * we copy all the names out of the directory before we start modifying + * it. + */ + filenames = pgfnames(path); + + if (filenames == NULL) + return false; + + /* now we have the names we can start removing things */ + for (filename = filenames; *filename; filename++) + { + snprintf(pathbuf, MAXPGPATH, "%s/%s", path, *filename); + + /* + * It's ok if the file is not there anymore; we were just about to + * delete it anyway. + * + * This is not an academic possibility. One scenario where this + * happens is when bgwriter has a pending unlink request for a file in + * a database that's being dropped. In dropdb(), we call + * ForgetDatabaseFsyncRequests() to flush out any such pending unlink + * requests, but because that's asynchronous, it's not guaranteed that + * the bgwriter receives the message in time. + */ + if (lstat(pathbuf, &statbuf) != 0) + { + if (errno != ENOENT) + { +#ifndef FRONTEND + elog(WARNING, "could not stat file or directory \"%s\": %m", + pathbuf); +#else + fprintf(stderr, _("could not stat file or directory \"%s\": %s\n"), + pathbuf, strerror(errno)); +#endif + result = false; + } + continue; + } + + if (S_ISDIR(statbuf.st_mode)) + { + /* call ourselves recursively for a directory */ + if (!rmtree(pathbuf, true)) + { + /* we already reported the error */ + result = false; + } + } + else + { + if (unlink(pathbuf) != 0) + { + if (errno != ENOENT) + { +#ifndef FRONTEND + elog(WARNING, "could not remove file or directory \"%s\": %m", + pathbuf); +#else + fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"), + pathbuf, strerror(errno)); +#endif + result = false; + } + } + } + } + + if (rmtopdir) + { + if (rmdir(path) != 0) + { +#ifndef FRONTEND + elog(WARNING, "could not remove file or directory \"%s\": %m", + path); +#else + fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"), + path, strerror(errno)); +#endif + result = false; + } + } + + pgfnames_cleanup(filenames); + + return result; +} diff --git a/src/port/dirmod.c b/src/port/dirmod.c index a18d2ef7ba..0a630ff697 100644 --- a/src/port/dirmod.c +++ b/src/port/dirmod.c @@ -351,116 +351,6 @@ pgwin32_is_junction(char *path) #endif /* defined(WIN32) && !defined(__CYGWIN__) */ -/* - * rmtree - * - * Delete a directory tree recursively. - * Assumes path points to a valid directory. - * Deletes everything under path. - * If rmtopdir is true deletes the directory too. - * Returns true if successful, false if there was any problem. - * (The details of the problem are reported already, so caller - * doesn't really have to say anything more, but most do.) - */ -bool -rmtree(const char *path, bool rmtopdir) -{ - bool result = true; - char pathbuf[MAXPGPATH]; - char **filenames; - char **filename; - struct stat statbuf; - - /* - * we copy all the names out of the directory before we start modifying - * it. - */ - filenames = pgfnames(path); - - if (filenames == NULL) - return false; - - /* now we have the names we can start removing things */ - for (filename = filenames; *filename; filename++) - { - snprintf(pathbuf, MAXPGPATH, "%s/%s", path, *filename); - - /* - * It's ok if the file is not there anymore; we were just about to - * delete it anyway. - * - * This is not an academic possibility. One scenario where this - * happens is when bgwriter has a pending unlink request for a file in - * a database that's being dropped. In dropdb(), we call - * ForgetDatabaseFsyncRequests() to flush out any such pending unlink - * requests, but because that's asynchronous, it's not guaranteed that - * the bgwriter receives the message in time. - */ - if (lstat(pathbuf, &statbuf) != 0) - { - if (errno != ENOENT) - { -#ifndef FRONTEND - elog(WARNING, "could not stat file or directory \"%s\": %m", - pathbuf); -#else - fprintf(stderr, _("could not stat file or directory \"%s\": %s\n"), - pathbuf, strerror(errno)); -#endif - result = false; - } - continue; - } - - if (S_ISDIR(statbuf.st_mode)) - { - /* call ourselves recursively for a directory */ - if (!rmtree(pathbuf, true)) - { - /* we already reported the error */ - result = false; - } - } - else - { - if (unlink(pathbuf) != 0) - { - if (errno != ENOENT) - { -#ifndef FRONTEND - elog(WARNING, "could not remove file or directory \"%s\": %m", - pathbuf); -#else - fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"), - pathbuf, strerror(errno)); -#endif - result = false; - } - } - } - } - - if (rmtopdir) - { - if (rmdir(path) != 0) - { -#ifndef FRONTEND - elog(WARNING, "could not remove file or directory \"%s\": %m", - path); -#else - fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"), - path, strerror(errno)); -#endif - result = false; - } - } - - pgfnames_cleanup(filenames); - - return result; -} - - #if defined(WIN32) && !defined(__CYGWIN__) #undef stat diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 2dc8b1d881..0e84348e4d 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -74,7 +74,7 @@ sub mkvcbuild win32error.c win32setlocale.c); our @pgcommonallfiles = qw( - exec.c pgfnames.c relpath.c wait_error.c); + exec.c pgfnames.c relpath.c rmtree.c wait_error.c); our @pgcommonfrontendfiles = (@pgcommonallfiles, qw(fe_memutils.c)); -- 2.40.0