Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * rmtree.c
4 : *
5 : * Portions Copyright (c) 1996-2023, 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 : #include "common/file_utils.h"
24 :
25 : #ifndef FRONTEND
26 : #include "storage/fd.h"
27 : #define pg_log_warning(...) elog(WARNING, __VA_ARGS__)
28 : #define LOG_LEVEL WARNING
29 : #define OPENDIR(x) AllocateDir(x)
30 : #define CLOSEDIR(x) FreeDir(x)
31 : #else
32 : #include "common/logging.h"
33 : #define LOG_LEVEL PG_LOG_WARNING
34 : #define OPENDIR(x) opendir(x)
35 : #define CLOSEDIR(x) closedir(x)
36 : #endif
37 :
38 : /*
39 : * rmtree
40 : *
41 : * Delete a directory tree recursively.
42 : * Assumes path points to a valid directory.
43 : * Deletes everything under path.
44 : * If rmtopdir is true deletes the directory too.
45 : * Returns true if successful, false if there was any problem.
46 : * (The details of the problem are reported already, so caller
47 : * doesn't really have to say anything more, but most do.)
48 : */
49 : bool
3459 peter_e 50 GIC 2862 : rmtree(const char *path, bool rmtopdir)
51 : {
52 : char pathbuf[MAXPGPATH];
53 : DIR *dir;
54 : struct dirent *de;
68 tmunro 55 GNC 2862 : bool result = true;
56 2862 : size_t dirnames_size = 0;
57 2862 : size_t dirnames_capacity = 8;
58 2862 : char **dirnames = palloc(sizeof(char *) * dirnames_capacity);
59 :
60 2862 : dir = OPENDIR(path);
61 2862 : if (dir == NULL)
68 tmunro 62 ECB : {
68 tmunro 63 UNC 0 : pg_log_warning("could not open directory \"%s\": %m", path);
3459 peter_e 64 0 : return false;
65 : }
3459 peter_e 66 EUB :
68 tmunro 67 GNC 129300 : while (errno = 0, (de = readdir(dir)))
68 : {
69 126438 : if (strcmp(de->d_name, ".") == 0 ||
70 123576 : strcmp(de->d_name, "..") == 0)
3459 peter_e 71 GIC 5724 : continue;
68 tmunro 72 GNC 120714 : snprintf(pathbuf, sizeof(pathbuf), "%s/%s", path, de->d_name);
73 120714 : switch (get_dirent_type(pathbuf, de, false, LOG_LEVEL))
74 : {
68 tmunro 75 UNC 0 : case PGFILETYPE_ERROR:
76 : /* already logged, press on */
77 0 : break;
68 tmunro 78 GNC 2312 : 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 2312 : if (dirnames_size == dirnames_capacity)
85 : {
86 170 : dirnames = repalloc(dirnames,
87 : sizeof(char *) * dirnames_capacity * 2);
88 170 : dirnames_capacity *= 2;
89 : }
90 2312 : dirnames[dirnames_size++] = pstrdup(pathbuf);
91 2312 : break;
92 118402 : default:
93 118402 : if (unlink(pathbuf) != 0 && errno != ENOENT)
94 : {
68 tmunro 95 UNC 0 : pg_log_warning("could not unlink file \"%s\": %m", pathbuf);
3459 peter_e 96 UIC 0 : result = false;
3459 peter_e 97 EUB : }
68 tmunro 98 GNC 118402 : break;
99 : }
100 : }
3459 peter_e 101 ECB :
68 tmunro 102 GNC 2862 : if (errno != 0)
103 : {
68 tmunro 104 UNC 0 : pg_log_warning("could not read directory \"%s\": %m", path);
105 0 : result = false;
106 : }
107 :
68 tmunro 108 GNC 2862 : CLOSEDIR(dir);
109 :
110 : /* Now recurse into the subdirectories we found. */
111 5174 : for (size_t i = 0; i < dirnames_size; ++i)
112 : {
113 2312 : if (!rmtree(dirnames[i], true))
68 tmunro 114 UNC 0 : result = false;
68 tmunro 115 GNC 2312 : pfree(dirnames[i]);
116 : }
117 :
3459 peter_e 118 GIC 2862 : if (rmtopdir)
119 : {
3459 peter_e 120 CBC 2862 : if (rmdir(path) != 0)
121 : {
68 tmunro 122 UNC 0 : pg_log_warning("could not remove directory \"%s\": %m", path);
3459 peter_e 123 LBC 0 : result = false;
124 : }
125 : }
3459 peter_e 126 ECB :
68 tmunro 127 GNC 2862 : pfree(dirnames);
3459 peter_e 128 ECB :
3459 peter_e 129 GIC 2862 : return result;
3459 peter_e 130 EUB : }
|