Import Debian changes 4.92-8+deb10u3
[hcoop/debian/exim4.git] / src / directory.c
CommitLineData
420a0d19
CE
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
5/* Copyright (c) University of Cambridge 1995 - 2009 */
2ea97746 6/* Copyright (c) The Exim Maintainers 2010 - 2018 */
420a0d19
CE
7/* See the file NOTICE for conditions of use and distribution. */
8
9#include "exim.h"
10
11
12/*************************************************
13* Attempt to create a directory *
14*************************************************/
15
16/* All the directories that Exim ever creates for itself are within the spool
17directory as defined by spool_directory. We are prepared to create as many as
18necessary from that directory downwards, inclusive. However, directory creation
19can also be required in appendfile and sieve filters. The making function
20therefore has a parent argument, below which the new directories are to go. It
21can be NULL if the name is absolute.
22
23If a non-root uid has been specified for exim, and we are currently running as
24root, ensure the directory is owned by the non-root id if the parent is the
25spool directory.
26
27Arguments:
28 parent parent directory name; if NULL the name must be absolute
29 name directory name within the parent that we want
30 mode mode for the new directory
31 panic if TRUE, panic on failure
32
33Returns: panic on failure if panic is set; otherwise return FALSE;
34 TRUE on success.
35*/
36
37BOOL
38directory_make(const uschar *parent, const uschar *name,
39 int mode, BOOL panic)
40{
41BOOL use_chown = parent == spool_directory && geteuid() == root_uid;
2ea97746
CE
42uschar * p;
43uschar c = 1;
420a0d19 44struct stat statbuf;
2ea97746 45uschar * path;
420a0d19 46
2ea97746 47if (parent)
420a0d19 48 {
2ea97746
CE
49 path = string_sprintf("%s%s%s", parent, US"/", name);
50 p = path + Ustrlen(parent);
420a0d19
CE
51 }
52else
53 {
2ea97746
CE
54 path = string_copy(name);
55 p = path + 1;
420a0d19
CE
56 }
57
2ea97746 58/* Walk the path creating any missing directories */
420a0d19 59
2ea97746 60while (c && *p)
420a0d19 61 {
2ea97746 62 while (*p && *p != '/') p++;
420a0d19 63 c = *p;
2ea97746
CE
64 *p = '\0';
65 if (Ustat(path, &statbuf) != 0)
420a0d19 66 {
2ea97746
CE
67 if (mkdir(CS path, mode) < 0 && errno != EEXIST)
68 { p = US"create"; goto bad; }
420a0d19
CE
69
70 /* Set the ownership if necessary. */
71
2ea97746
CE
72 if (use_chown && Uchown(path, exim_uid, exim_gid))
73 { p = US"set owner on"; goto bad; }
420a0d19
CE
74
75 /* It appears that any mode bits greater than 0777 are ignored by
76 mkdir(), at least on some operating systems. Therefore, if the mode
77 contains any such bits, do an explicit mode setting. */
78
2ea97746 79 if (mode & 0777000) (void) Uchmod(path, mode);
420a0d19
CE
80 }
81 *p++ = c;
82 }
83
84return TRUE;
2ea97746
CE
85
86bad:
87 if (panic) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
88 "Failed to %s directory \"%s\": %s\n", p, path, strerror(errno));
89 return FALSE;
420a0d19
CE
90}
91
92/* End of directory.c */