PostgreSQL Source Code  git master
rmtree.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * rmtree.c
4  *
5  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  * IDENTIFICATION
9  * src/common/rmtree.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #ifndef FRONTEND
15 #include "postgres.h"
16 #else
17 #include "postgres_fe.h"
18 #endif
19 
20 #include <unistd.h>
21 #include <sys/stat.h>
22 
23 #ifndef FRONTEND
24 #define pg_log_warning(...) elog(WARNING, __VA_ARGS__)
25 #else
26 #include "common/logging.h"
27 #endif
28 
29 
30 /*
31  * rmtree
32  *
33  * Delete a directory tree recursively.
34  * Assumes path points to a valid directory.
35  * Deletes everything under path.
36  * If rmtopdir is true deletes the directory too.
37  * Returns true if successful, false if there was any problem.
38  * (The details of the problem are reported already, so caller
39  * doesn't really have to say anything more, but most do.)
40  */
41 bool
42 rmtree(const char *path, bool rmtopdir)
43 {
44  bool result = true;
45  char pathbuf[MAXPGPATH];
46  char **filenames;
47  char **filename;
48  struct stat statbuf;
49 
50  /*
51  * we copy all the names out of the directory before we start modifying
52  * it.
53  */
54  filenames = pgfnames(path);
55 
56  if (filenames == NULL)
57  return false;
58 
59  /* now we have the names we can start removing things */
60  for (filename = filenames; *filename; filename++)
61  {
62  snprintf(pathbuf, MAXPGPATH, "%s/%s", path, *filename);
63 
64  /*
65  * It's ok if the file is not there anymore; we were just about to
66  * delete it anyway.
67  *
68  * This is not an academic possibility. One scenario where this
69  * happens is when bgwriter has a pending unlink request for a file in
70  * a database that's being dropped. In dropdb(), we call
71  * ForgetDatabaseSyncRequests() to flush out any such pending unlink
72  * requests, but because that's asynchronous, it's not guaranteed that
73  * the bgwriter receives the message in time.
74  */
75  if (lstat(pathbuf, &statbuf) != 0)
76  {
77  if (errno != ENOENT)
78  {
79  pg_log_warning("could not stat file or directory \"%s\": %m",
80  pathbuf);
81  result = false;
82  }
83  continue;
84  }
85 
86  if (S_ISDIR(statbuf.st_mode))
87  {
88  /* call ourselves recursively for a directory */
89  if (!rmtree(pathbuf, true))
90  {
91  /* we already reported the error */
92  result = false;
93  }
94  }
95  else
96  {
97  if (unlink(pathbuf) != 0)
98  {
99  if (errno != ENOENT)
100  {
101  pg_log_warning("could not remove file or directory \"%s\": %m",
102  pathbuf);
103  result = false;
104  }
105  }
106  }
107  }
108 
109  if (rmtopdir)
110  {
111  if (rmdir(path) != 0)
112  {
113  pg_log_warning("could not remove file or directory \"%s\": %m",
114  path);
115  result = false;
116  }
117  }
118 
119  pgfnames_cleanup(filenames);
120 
121  return result;
122 }
char ** pgfnames(const char *path)
Definition: pgfnames.c:37
#define MAXPGPATH
#define pg_log_warning(...)
Definition: rmtree.c:24
#define stat(a, b)
Definition: win32_port.h:255
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:42
void pgfnames_cleanup(char **filenames)
Definition: pgfnames.c:86
#define S_ISDIR(m)
Definition: win32_port.h:296
#define lstat(path, sb)
Definition: win32_port.h:244
static char * filename
Definition: pg_dumpall.c:90
#define snprintf
Definition: port.h:192