* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2014 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions in support of the use of maildirsize files for handling quotas in
/* If the basic path matches maildirfolder_create_regex, we are dealing with
a subfolder, and should ensure that a maildirfolder file exists. */
-if (maildirfolder_create_regex != NULL)
+if (maildirfolder_create_regex)
{
- const uschar *error;
- int offset;
- const pcre *regex;
+ int err;
+ PCRE2_SIZE offset;
+ const pcre2_code * re;
DEBUG(D_transport) debug_printf("checking for maildirfolder requirement\n");
- regex = pcre_compile(CS maildirfolder_create_regex, PCRE_COPT,
- (const char **)&error, &offset, NULL);
-
- if (regex == NULL)
+ if (!(re = pcre2_compile((PCRE2_SPTR)maildirfolder_create_regex,
+ PCRE2_ZERO_TERMINATED, PCRE_COPT, &err, &offset, pcre_cmp_ctx)))
{
+ uschar errbuf[128];
+ pcre2_get_error_message(err, errbuf, sizeof(errbuf));
addr->message = string_sprintf("appendfile: regular expression "
- "error: %s at offset %d while compiling %s", error, offset,
+ "error: %s at offset %ld while compiling %s", errbuf, (long)offset,
maildirfolder_create_regex);
return FALSE;
}
- if (pcre_exec(regex, NULL, CS path, Ustrlen(path), 0, 0, NULL, 0) >= 0)
+ if (regex_match(re, path, -1, NULL))
{
uschar *fname = string_sprintf("%s/maildirfolder", path);
if (Ustat(fname, &statbuf) == 0)
uschar buffer[256];
sprintf(CS buffer, "%d 1\n", size);
len = Ustrlen(buffer);
-(void)lseek(fd, 0, SEEK_END);
-len = write(fd, buffer, len);
-DEBUG(D_transport)
- debug_printf("added '%.*s' to maildirsize file\n", len-1, buffer);
+if (lseek(fd, 0, SEEK_END) >= 0)
+ {
+ len = write(fd, buffer, len);
+ DEBUG(D_transport)
+ debug_printf("added '%.*s' to maildirsize file\n", len-1, buffer);
+ }
}
off_t
maildir_compute_size(uschar *path, int *filecount, time_t *latest,
- const pcre *regex, const pcre *dir_regex, BOOL timestamp_only)
+ const pcre2_code *regex, const pcre2_code *dir_regex, BOOL timestamp_only)
{
DIR *dir;
off_t sum = 0;
-struct dirent *ent;
-struct stat statbuf;
-dir = opendir(CS path);
-if (dir == NULL) return 0;
+if (!(dir = exim_opendir(path)))
+ return 0;
-while ((ent = readdir(dir)) != NULL)
+for (struct dirent *ent; ent = readdir(dir); )
{
- uschar *name = US ent->d_name;
- uschar buffer[1024];
+ uschar * s, * name = US ent->d_name;
+ struct stat statbuf;
if (Ustrcmp(name, ".") == 0 || Ustrcmp(name, "..") == 0) continue;
scan. We do the regex match first, because that avoids a stat() for names
we aren't interested in. */
- if (dir_regex != NULL &&
- pcre_exec(dir_regex, NULL, CS name, Ustrlen(name), 0, 0, NULL, 0) < 0)
+ if (dir_regex && !regex_match(dir_regex, name, -1, NULL))
{
DEBUG(D_transport)
debug_printf("skipping %s/%s: dir_regex does not match\n", path, name);
/* The name is OK; stat it. */
- if (!string_format(buffer, sizeof(buffer), "%s/%s", path, name))
- {
- DEBUG(D_transport)
- debug_printf("maildir_compute_size: name too long: dir=%s name=%s\n",
- path, name);
- continue;
- }
-
- if (Ustat(buffer, &statbuf) < 0)
+ s = string_sprintf("%s/%s", path, name);
+ if (Ustat(s, &statbuf) < 0)
{
DEBUG(D_transport)
debug_printf("maildir_compute_size: stat error %d for %s: %s\n", errno,
- buffer, strerror(errno));
+ s, strerror(errno));
continue;
}
if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
{
DEBUG(D_transport)
- debug_printf("skipping %s/%s: not a directory\n", path, name);
+ debug_printf("skipping %s/%s: not a directory\n", s, name);
continue;
}
/* If this is a maildir folder, call this function recursively. */
if (name[0] == '.')
- {
- sum += maildir_compute_size(buffer, filecount, latest, regex, dir_regex,
+ sum += maildir_compute_size(s, filecount, latest, regex, dir_regex,
timestamp_only);
- }
/* Otherwise it must be a folder that contains messages (e.g. new or cur), so
we need to get its size, unless all we are interested in is the timestamp. */
else if (!timestamp_only)
- {
- sum += check_dir_size(buffer, filecount, regex);
- }
+ sum += check_dir_size(s, filecount, regex);
}
closedir(dir);
int
maildir_ensure_sizefile(uschar *path, appendfile_transport_options_block *ob,
- const pcre *regex, const pcre *dir_regex, off_t *returned_size,
+ const pcre2_code *regex, const pcre2_code *dir_regex, off_t *returned_size,
int *returned_filecount)
{
int count, fd;
filename = string_sprintf("%s/maildirsize", path);
DEBUG(D_transport) debug_printf("looking for maildirsize in %s\n", path);
-fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600);
-if (fd < 0)
+if ((fd = Uopen(filename, O_RDWR|O_APPEND, ob->mode ? ob->mode : 0600)) < 0)
{
if (errno != ENOENT) return -1;
DEBUG(D_transport)
still correct, and that the size of the file is still small enough. If so,
compute the maildir size from the file. */
-count = read(fd, buffer, sizeof(buffer));
-if (count >= sizeof(buffer))
+if ((count = read(fd, buffer, sizeof(buffer))) >= sizeof(buffer))
{
DEBUG(D_transport)
debug_printf("maildirsize file too big (%d): recalculating\n", count);