Coverage Report

Created: 2026-05-30 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}