PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
rmtree.c File Reference
#include "postgres.h"
#include <unistd.h>
#include <sys/stat.h>
Include dependency graph for rmtree.c:

Go to the source code of this file.

Functions

bool rmtree (const char *path, bool rmtopdir)
 

Function Documentation

bool rmtree ( const char *  path,
bool  rmtopdir 
)

Definition at line 36 of file rmtree.c.

References _, elog, filename, lstat, MAXPGPATH, pgfnames(), pgfnames_cleanup(), rmtree(), snprintf(), strerror(), and WARNING.

Referenced by cleanup_directories_atexit(), convert_sourcefiles_in(), create_tablespace_directories(), CreateSlotOnDisk(), dbase_redo(), exit_nicely(), movedb(), movedb_failure_callback(), regression_main(), remove_dbtablespaces(), remove_new_subdir(), ReplicationSlotDropPtr(), RestoreSlotFromDisk(), rmtree(), and StartupReplicationSlots().

37 {
38  bool result = true;
39  char pathbuf[MAXPGPATH];
40  char **filenames;
41  char **filename;
42  struct stat statbuf;
43 
44  /*
45  * we copy all the names out of the directory before we start modifying
46  * it.
47  */
48  filenames = pgfnames(path);
49 
50  if (filenames == NULL)
51  return false;
52 
53  /* now we have the names we can start removing things */
54  for (filename = filenames; *filename; filename++)
55  {
56  snprintf(pathbuf, MAXPGPATH, "%s/%s", path, *filename);
57 
58  /*
59  * It's ok if the file is not there anymore; we were just about to
60  * delete it anyway.
61  *
62  * This is not an academic possibility. One scenario where this
63  * happens is when bgwriter has a pending unlink request for a file in
64  * a database that's being dropped. In dropdb(), we call
65  * ForgetDatabaseFsyncRequests() to flush out any such pending unlink
66  * requests, but because that's asynchronous, it's not guaranteed that
67  * the bgwriter receives the message in time.
68  */
69  if (lstat(pathbuf, &statbuf) != 0)
70  {
71  if (errno != ENOENT)
72  {
73 #ifndef FRONTEND
74  elog(WARNING, "could not stat file or directory \"%s\": %m",
75  pathbuf);
76 #else
77  fprintf(stderr, _("could not stat file or directory \"%s\": %s\n"),
78  pathbuf, strerror(errno));
79 #endif
80  result = false;
81  }
82  continue;
83  }
84 
85  if (S_ISDIR(statbuf.st_mode))
86  {
87  /* call ourselves recursively for a directory */
88  if (!rmtree(pathbuf, true))
89  {
90  /* we already reported the error */
91  result = false;
92  }
93  }
94  else
95  {
96  if (unlink(pathbuf) != 0)
97  {
98  if (errno != ENOENT)
99  {
100 #ifndef FRONTEND
101  elog(WARNING, "could not remove file or directory \"%s\": %m",
102  pathbuf);
103 #else
104  fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
105  pathbuf, strerror(errno));
106 #endif
107  result = false;
108  }
109  }
110  }
111  }
112 
113  if (rmtopdir)
114  {
115  if (rmdir(path) != 0)
116  {
117 #ifndef FRONTEND
118  elog(WARNING, "could not remove file or directory \"%s\": %m",
119  path);
120 #else
121  fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
122  path, strerror(errno));
123 #endif
124  result = false;
125  }
126  }
127 
128  pgfnames_cleanup(filenames);
129 
130  return result;
131 }
char ** pgfnames(const char *path)
Definition: pgfnames.c:31
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define MAXPGPATH
#define WARNING
Definition: elog.h:40
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:36
void pgfnames_cleanup(char **filenames)
Definition: pgfnames.c:99
static char * filename
Definition: pg_dumpall.c:90
const char * strerror(int errnum)
Definition: strerror.c:19
#define elog
Definition: elog.h:219
#define lstat(path, sb)
Definition: win32.h:262
#define _(x)
Definition: elog.c:84