* walkdir: recursively walk a directory, applying the action to each * regular file and directory (including the named directory itself). * * If process_symlinks is true, the action and recursion are also applied * to regular files and directories that are pointed to by symlinks in the * given directory; otherwise symlinks are ignored. Symlinks are always * ignored in subdirectories, ie we
| 153 | * See also walkdir in fd.c, which is a backend version of this logic. |
| 154 | */ |
| 155 | static void |
| 156 | walkdir(const char *path, |
| 157 | int (*action) (const char *fname, bool isdir), |
| 158 | bool process_symlinks) |
| 159 | { |
| 160 | DIR *dir; |
| 161 | struct dirent *de; |
| 162 | |
| 163 | dir = opendir(path); |
| 164 | if (dir == NULL) |
| 165 | { |
| 166 | pg_log_error("could not open directory \"%s\": %m", path); |
| 167 | return; |
| 168 | } |
| 169 | |
| 170 | while (errno = 0, (de = readdir(dir)) != NULL) |
| 171 | { |
| 172 | char subpath[MAXPGPATH * 2]; |
| 173 | |
| 174 | if (strcmp(de->d_name, ".") == 0 || |
| 175 | strcmp(de->d_name, "..") == 0) |
| 176 | continue; |
| 177 | |
| 178 | snprintf(subpath, sizeof(subpath), "%s/%s", path, de->d_name); |
| 179 | |
| 180 | switch (get_dirent_type(subpath, de, process_symlinks, PG_LOG_ERROR)) |
| 181 | { |
| 182 | case PGFILETYPE_REG: |
| 183 | (*action) (subpath, false); |
| 184 | break; |
| 185 | case PGFILETYPE_DIR: |
| 186 | walkdir(subpath, action, false); |
| 187 | break; |
| 188 | default: |
| 189 | |
| 190 | /* |
| 191 | * Errors are already reported directly by get_dirent_type(), |
| 192 | * and any remaining symlinks and unknown file types are |
| 193 | * ignored. |
| 194 | */ |
| 195 | break; |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | if (errno) |
| 200 | pg_log_error("could not read directory \"%s\": %m", path); |
| 201 | |
| 202 | (void) closedir(dir); |
| 203 | |
| 204 | /* |
| 205 | * It's important to fsync the destination directory itself as individual |
| 206 | * file fsyncs don't guarantee that the directory entry for the file is |
| 207 | * synced. Recent versions of ext4 have made the window much wider but |
| 208 | * it's been an issue for ext3 and other filesystems in the past. |
| 209 | */ |
| 210 | (*action) (path, true); |
| 211 | } |
| 212 |
no test coverage detected