diff --git a/Makefile b/Makefile
index 1fe7ec6b..bbf778fd 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
HEADERS = $(wildcard *.h)
repmgrd_OBJS = dbutils.o config.o repmgrd.o log.o strutil.o
-repmgr_OBJS = dbutils.o check_dir.o config.o repmgr.o log.o strutil.o
+repmgr_OBJS = dbutils.o check_dir.o config.o repmgr.o log.o strutil.o dirmod.o
DATA = repmgr.sql uninstall_repmgr.sql
diff --git a/dirmod.c b/dirmod.c
new file mode 100644
index 00000000..82837f66
--- /dev/null
+++ b/dirmod.c
@@ -0,0 +1,194 @@
+/*
+ *
+ * dirmod.c
+ * directory handling functions
+ *
+ * Copyright (C) 2ndQuadrant, 2010-2016
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "postgres_fe.h"
+
+/* Don't modify declarations in system headers */
+
+#include
+#include
+#include
+
+/*
+ * pgfnames
+ *
+ * return a list of the names of objects in the argument directory. Caller
+ * must call pgfnames_cleanup later to free the memory allocated by this
+ * function.
+ */
+char **
+pgfnames(const char *path)
+{
+ DIR *dir;
+ struct dirent *file;
+ char **filenames;
+ int numnames = 0;
+ int fnsize = 200; /* enough for many small dbs */
+
+ dir = opendir(path);
+ if (dir == NULL)
+ {
+ return NULL;
+ }
+
+ filenames = (char **) palloc(fnsize * sizeof(char *));
+
+ while (errno = 0, (file = readdir(dir)) != NULL)
+ {
+ if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
+ {
+ if (numnames + 1 >= fnsize)
+ {
+ fnsize *= 2;
+ filenames = (char **) repalloc(filenames,
+ fnsize * sizeof(char *));
+ }
+ filenames[numnames++] = pstrdup(file->d_name);
+ }
+ }
+
+ if (errno)
+ {
+ fprintf(stderr, _("could not read directory \"%s\": %s\n"),
+ path, strerror(errno));
+ }
+
+ filenames[numnames] = NULL;
+
+ if (closedir(dir))
+ {
+ fprintf(stderr, _("could not close directory \"%s\": %s\n"),
+ path, strerror(errno));
+ }
+
+ return filenames;
+}
+
+
+/*
+ * pgfnames_cleanup
+ *
+ * deallocate memory used for filenames
+ */
+void
+pgfnames_cleanup(char **filenames)
+{
+ char **fn;
+
+ for (fn = filenames; *fn; fn++)
+ pfree(*fn);
+
+ pfree(filenames);
+}
+
+
+/*
+ * 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)
+ {
+ 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)
+ {
+ result = false;
+ }
+ }
+ }
+ }
+
+ if (rmtopdir)
+ {
+ if (rmdir(path) != 0)
+ {
+ result = false;
+ }
+ }
+
+ pgfnames_cleanup(filenames);
+
+ return result;
+}
+
diff --git a/dirmod.h b/dirmod.h
new file mode 100644
index 00000000..47caf982
--- /dev/null
+++ b/dirmod.h
@@ -0,0 +1,23 @@
+/*
+ * dirmod.h
+ * Copyright (c) 2ndQuadrant, 2010-2016
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#ifndef _DIRMOD_H_
+#define _DIRMOD_H_
+
+#endif
diff --git a/repmgr.c b/repmgr.c
index 6e7f10bb..aa340b62 100644
--- a/repmgr.c
+++ b/repmgr.c
@@ -1332,6 +1332,8 @@ do_standby_clone(void)
char *first_wal_segment = NULL;
char *last_wal_segment = NULL;
+ char xlog_dir[MAXLEN] = "";
+
PQExpBufferData event_details;
@@ -1997,15 +1999,16 @@ stop_backup:
* Remove any existing WAL from the target directory, since
* rsync's --exclude option doesn't do it.
*/
- maxlen_snprintf(script, "rm -rf %s/pg_xlog/*",
- local_data_directory);
- r = system(script);
- if (r != 0)
+
+ maxlen_snprintf(xlog_dir, "%s/pg_xlog/", local_data_directory);
+
+ if (!rmtree(xlog_dir, false))
{
- log_err(_("unable to empty local WAL directory %s/pg_xlog/\n"),
- local_data_directory);
+ log_err(_("unable to empty local WAL directory %s\n"),
+ xlog_dir);
exit(ERR_BAD_RSYNC);
}
+
}
/*
diff --git a/repmgr.h b/repmgr.h
index 780dccf7..4141c7fd 100644
--- a/repmgr.h
+++ b/repmgr.h
@@ -28,6 +28,7 @@
#include "dbutils.h"
#include "errcode.h"
#include "config.h"
+#include "dirmod.h"
#define MIN_SUPPORTED_VERSION "9.3"
#define MIN_SUPPORTED_VERSION_NUM 90300