bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include "lib.h"
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include "ioloop.h"
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include "str.h"
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include "unlink-old-files.h"
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include <signal.h>
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include <unistd.h>
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include <dirent.h>
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include <sys/stat.h>
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen#include <utime.h>
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainenstatic int
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainenunlink_old_files_real(const char *dir, const char *prefix, time_t min_time)
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen{
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen DIR *dirp;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen struct dirent *d;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen struct stat st;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen string_t *path;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t prefix_len, dir_len;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen dirp = opendir(dir);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (dirp == NULL) {
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (errno != ENOENT)
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen i_error("opendir(%s) failed: %m", dir);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen return -1;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen }
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
e736ac97fd3896533f4ebf3b18a791bc3637b711Timo Sirainen /* update atime immediately, so if this scanning is done based on
e736ac97fd3896533f4ebf3b18a791bc3637b711Timo Sirainen atime it won't be done by multiple processes if the scan is slow */
e736ac97fd3896533f4ebf3b18a791bc3637b711Timo Sirainen if (utime(dir, NULL) < 0 && errno != ENOENT)
e736ac97fd3896533f4ebf3b18a791bc3637b711Timo Sirainen i_error("utime(%s) failed: %m", dir);
e736ac97fd3896533f4ebf3b18a791bc3637b711Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen path = t_str_new(256);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen str_printfa(path, "%s/", dir);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen dir_len = str_len(path);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen prefix_len = strlen(prefix);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen while ((d = readdir(dirp)) != NULL) {
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (d->d_name[0] == '.' &&
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen (d->d_name[1] == '\0' ||
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen (d->d_name[1] == '.' && d->d_name[2] == '\0'))) {
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen /* skip . and .. */
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen continue;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen }
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (strncmp(d->d_name, prefix, prefix_len) != 0)
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen continue;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen str_truncate(path, dir_len);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen str_append(path, d->d_name);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (stat(str_c(path), &st) < 0) {
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (errno != ENOENT)
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen i_error("stat(%s) failed: %m", str_c(path));
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen } else if (!S_ISDIR(st.st_mode) && st.st_ctime < min_time) {
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink_if_exists(str_c(path));
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen }
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen }
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen if (closedir(dirp) < 0)
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen i_error("closedir(%s) failed: %m", dir);
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen return 0;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen}
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainenint unlink_old_files(const char *dir, const char *prefix, time_t min_time)
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen{
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen int ret;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen ret = unlink_old_files_real(dir, prefix, min_time);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen return ret;
0791d5779d67da0983375dc01dadec4c749b6f38Timo Sirainen}