/src/dovecot/src/lib/unlink-old-files.c
Line | Count | Source |
1 | | /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ |
2 | | |
3 | | #include "lib.h" |
4 | | #include "ioloop.h" |
5 | | #include "str.h" |
6 | | #include "unlink-old-files.h" |
7 | | |
8 | | #include <signal.h> |
9 | | #include <unistd.h> |
10 | | #include <dirent.h> |
11 | | #include <sys/stat.h> |
12 | | #include <utime.h> |
13 | | |
14 | | static int |
15 | | unlink_old_files_real(const char *dir, const char *prefix, time_t min_time) |
16 | 0 | { |
17 | 0 | DIR *dirp; |
18 | 0 | struct dirent *d; |
19 | 0 | struct stat st; |
20 | 0 | string_t *path; |
21 | 0 | size_t prefix_len, dir_len; |
22 | |
|
23 | 0 | dirp = opendir(dir); |
24 | 0 | if (dirp == NULL) { |
25 | 0 | if (errno != ENOENT) |
26 | 0 | i_error("opendir(%s) failed: %m", dir); |
27 | 0 | return -1; |
28 | 0 | } |
29 | | |
30 | | /* update atime immediately, so if this scanning is done based on |
31 | | atime it won't be done by multiple processes if the scan is slow */ |
32 | 0 | if (utime(dir, NULL) < 0 && errno != ENOENT) |
33 | 0 | i_error("utime(%s) failed: %m", dir); |
34 | |
|
35 | 0 | path = t_str_new(256); |
36 | 0 | str_printfa(path, "%s/", dir); |
37 | 0 | dir_len = str_len(path); |
38 | |
|
39 | 0 | prefix_len = strlen(prefix); |
40 | 0 | while ((d = readdir(dirp)) != NULL) { |
41 | 0 | if (d->d_name[0] == '.' && |
42 | 0 | (d->d_name[1] == '\0' || |
43 | 0 | (d->d_name[1] == '.' && d->d_name[2] == '\0'))) { |
44 | | /* skip . and .. */ |
45 | 0 | continue; |
46 | 0 | } |
47 | 0 | if (strncmp(d->d_name, prefix, prefix_len) != 0) |
48 | 0 | continue; |
49 | | |
50 | 0 | str_truncate(path, dir_len); |
51 | 0 | str_append(path, d->d_name); |
52 | 0 | if (stat(str_c(path), &st) < 0) { |
53 | 0 | if (errno != ENOENT) |
54 | 0 | i_error("stat(%s) failed: %m", str_c(path)); |
55 | 0 | } else if (!S_ISDIR(st.st_mode) && st.st_ctime < min_time) { |
56 | 0 | i_unlink_if_exists(str_c(path)); |
57 | 0 | } |
58 | 0 | } |
59 | |
|
60 | 0 | if (closedir(dirp) < 0) |
61 | 0 | i_error("closedir(%s) failed: %m", dir); |
62 | 0 | return 0; |
63 | 0 | } |
64 | | |
65 | | int unlink_old_files(const char *dir, const char *prefix, time_t min_time) |
66 | 0 | { |
67 | 0 | int ret; |
68 | |
|
69 | 0 | T_BEGIN { |
70 | 0 | ret = unlink_old_files_real(dir, prefix, min_time); |
71 | 0 | } T_END; |
72 | 0 | return ret; |
73 | 0 | } |