Disable EXIM_MONITOR
[exim.git] / src / src / directory.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
0a49a7a4 5/* Copyright (c) University of Cambridge 1995 - 2009 */
f9ba5e22 6/* Copyright (c) The Exim Maintainers 2010 - 2018 */
059ec3d9
PH
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
1ba28e2b
PP
38directory_make(const uschar *parent, const uschar *name,
39 int mode, BOOL panic)
059ec3d9
PH
40{
41BOOL use_chown = parent == spool_directory && geteuid() == root_uid;
424fa2f3
JH
42uschar * p;
43uschar c = 1;
059ec3d9 44struct stat statbuf;
424fa2f3 45uschar * path;
059ec3d9 46
424fa2f3 47if (parent)
059ec3d9 48 {
424fa2f3
JH
49 path = string_sprintf("%s%s%s", parent, US"/", name);
50 p = path + Ustrlen(parent);
059ec3d9
PH
51 }
52else
53 {
424fa2f3
JH
54 path = string_copy(name);
55 p = path + 1;
059ec3d9
PH
56 }
57
424fa2f3 58/* Walk the path creating any missing directories */
059ec3d9 59
424fa2f3 60while (c && *p)
059ec3d9 61 {
424fa2f3 62 while (*p && *p != '/') p++;
059ec3d9 63 c = *p;
424fa2f3
JH
64 *p = '\0';
65 if (Ustat(path, &statbuf) != 0)
059ec3d9 66 {
424fa2f3
JH
67 if (mkdir(CS path, mode) < 0 && errno != EEXIST)
68 { p = US"create"; goto bad; }
059ec3d9
PH
69
70 /* Set the ownership if necessary. */
71
b66fecb4 72 if (use_chown && exim_chown(path, exim_uid, exim_gid))
424fa2f3 73 { p = US"set owner on"; goto bad; }
059ec3d9
PH
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
424fa2f3 79 if (mode & 0777000) (void) Uchmod(path, mode);
059ec3d9
PH
80 }
81 *p++ = c;
82 }
83
84return TRUE;
424fa2f3
JH
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;
059ec3d9
PH
90}
91
92/* End of directory.c */