--- /dev/null
+/* $Cambridge: exim/src/src/directory.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+#include "exim.h"
+
+
+/*************************************************
+* Attempt to create a directory *
+*************************************************/
+
+/* All the directories that Exim ever creates for itself are within the spool
+directory as defined by spool_directory. We are prepared to create as many as
+necessary from that directory downwards, inclusive. However, directory creation
+can also be required in appendfile and sieve filters. The making function
+therefore has a parent argument, below which the new directories are to go. It
+can be NULL if the name is absolute.
+
+If a non-root uid has been specified for exim, and we are currently running as
+root, ensure the directory is owned by the non-root id if the parent is the
+spool directory.
+
+Arguments:
+ parent parent directory name; if NULL the name must be absolute
+ name directory name within the parent that we want
+ mode mode for the new directory
+ panic if TRUE, panic on failure
+
+Returns: panic on failure if panic is set; otherwise return FALSE;
+ TRUE on success.
+*/
+
+BOOL
+directory_make(uschar *parent, uschar *name, int mode, BOOL panic)
+{
+BOOL use_chown = parent == spool_directory && geteuid() == root_uid;
+uschar *p, *slash;
+int c = 1;
+struct stat statbuf;
+uschar buffer[256];
+
+if (parent == NULL)
+ {
+ p = buffer + 1;
+ slash = parent = US"";
+ }
+else
+ {
+ p = buffer + Ustrlen(parent);
+ slash = US"/";
+ }
+
+if (!string_format(buffer, sizeof(buffer), "%s%s%s", parent, slash, name))
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE, "name too long in directory_make");
+
+while (c != 0 && *p != 0)
+ {
+ while (*p != 0 && *p != '/') p++;
+ c = *p;
+ *p = 0;
+ if (Ustat(buffer, &statbuf) != 0)
+ {
+ if (mkdir(CS buffer, mode) < 0 && errno != EEXIST)
+ {
+ if (!panic) return FALSE;
+ log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+ "Failed to create directory \"%s\": %s\n", buffer, strerror(errno));
+ }
+
+ /* Set the ownership if necessary. */
+
+ if (use_chown) Uchown(buffer, exim_uid, exim_gid);
+
+ /* It appears that any mode bits greater than 0777 are ignored by
+ mkdir(), at least on some operating systems. Therefore, if the mode
+ contains any such bits, do an explicit mode setting. */
+
+ if ((mode & 0777000) != 0) Uchmod(buffer, mode);
+ }
+ *p++ = c;
+ }
+
+return TRUE;
+}
+
+/* End of directory.c */