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