PostgreSQL Source Code  git master
rmtree.c File Reference
#include "postgres.h"
#include <unistd.h>
#include <sys/stat.h>
#include "common/file_utils.h"
#include "storage/fd.h"
Include dependency graph for rmtree.c:

Go to the source code of this file.

Macros

#define pg_log_warning(...)   elog(WARNING, __VA_ARGS__)
 
#define LOG_LEVEL   WARNING
 
#define OPENDIR(x)   AllocateDir(x)
 
#define CLOSEDIR(x)   FreeDir(x)
 

Functions

bool rmtree (const char *path, bool rmtopdir)
 

Macro Definition Documentation

◆ CLOSEDIR

#define CLOSEDIR (   x)    FreeDir(x)

Definition at line 30 of file rmtree.c.

◆ LOG_LEVEL

#define LOG_LEVEL   WARNING

Definition at line 28 of file rmtree.c.

◆ OPENDIR

#define OPENDIR (   x)    AllocateDir(x)

Definition at line 29 of file rmtree.c.

◆ pg_log_warning

#define pg_log_warning (   ...)    elog(WARNING, __VA_ARGS__)

Definition at line 27 of file rmtree.c.

Function Documentation

◆ rmtree()

bool rmtree ( const char *  path,
bool  rmtopdir 
)

Definition at line 50 of file rmtree.c.

51 {
52  char pathbuf[MAXPGPATH];
53  DIR *dir;
54  struct dirent *de;
55  bool result = true;
56  size_t dirnames_size = 0;
57  size_t dirnames_capacity = 8;
58  char **dirnames = palloc(sizeof(char *) * dirnames_capacity);
59 
60  dir = OPENDIR(path);
61  if (dir == NULL)
62  {
63  pg_log_warning("could not open directory \"%s\": %m", path);
64  return false;
65  }
66 
67  while (errno = 0, (de = readdir(dir)))
68  {
69  if (strcmp(de->d_name, ".") == 0 ||
70  strcmp(de->d_name, "..") == 0)
71  continue;
72  snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
73  switch (get_dirent_type(pathbuf, de, false, LOG_LEVEL))
74  {
75  case PGFILETYPE_ERROR:
76  /* already logged, press on */
77  break;
78  case PGFILETYPE_DIR:
79 
80  /*
81  * Defer recursion until after we've closed this directory, to
82  * avoid using more than one file descriptor at a time.
83  */
84  if (dirnames_size == dirnames_capacity)
85  {
86  dirnames = repalloc(dirnames,
87  sizeof(char *) * dirnames_capacity * 2);
88  dirnames_capacity *= 2;
89  }
90  dirnames[dirnames_size++] = pstrdup(pathbuf);
91  break;
92  default:
93  if (unlink(pathbuf) != 0 && errno != ENOENT)
94  {
95  pg_log_warning("could not unlink file \"%s\": %m", pathbuf);
96  result = false;
97  }
98  break;
99  }
100  }
101 
102  if (errno != 0)
103  {
104  pg_log_warning("could not read directory \"%s\": %m", path);
105  result = false;
106  }
107 
108  CLOSEDIR(dir);
109 
110  /* Now recurse into the subdirectories we found. */
111  for (size_t i = 0; i < dirnames_size; ++i)
112  {
113  if (!rmtree(dirnames[i], true))
114  result = false;
115  pfree(dirnames[i]);
116  }
117 
118  if (rmtopdir)
119  {
120  if (rmdir(path) != 0)
121  {
122  pg_log_warning("could not remove directory \"%s\": %m", path);
123  result = false;
124  }
125  }
126 
127  pfree(dirnames);
128 
129  return result;
130 }
struct dirent * readdir(DIR *)
Definition: dirent.c:78
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:406
@ PGFILETYPE_DIR
Definition: file_utils.h:23
@ PGFILETYPE_ERROR
Definition: file_utils.h:20
int i
Definition: isn.c:73
char * pstrdup(const char *in)
Definition: mcxt.c:1624
void pfree(void *pointer)
Definition: mcxt.c:1436
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1210
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define LOG_LEVEL
Definition: rmtree.c:28
#define OPENDIR(x)
Definition: rmtree.c:29
#define CLOSEDIR(x)
Definition: rmtree.c:30
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:50
#define pg_log_warning(...)
Definition: rmtree.c:27
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References CLOSEDIR, dirent::d_name, get_dirent_type(), i, LOG_LEVEL, MAXPGPATH, OPENDIR, palloc(), pfree(), pg_log_warning, PGFILETYPE_DIR, PGFILETYPE_ERROR, pstrdup(), readdir(), repalloc(), and snprintf.

Referenced by cleanup_directories_atexit(), cleanup_output_dirs(), CreateSlotOnDisk(), dbase_redo(), movedb(), movedb_failure_callback(), regression_main(), remove_dbtablespaces(), remove_new_subdir(), ReplicationSlotDropPtr(), RestoreSlotFromDisk(), and StartupReplicationSlots().