build: use pkg-config for i18n
[exim.git] / src / src / directory.c
index c6d46aa5dadce985e89d8887ae17bc5db87b6f9f..84646b4b3017396f58188ee7c01feee7ec57bc43 100644 (file)
@@ -2,8 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2010 - 2024 */
 /* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 /* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 #include "exim.h"
 
 
 #include "exim.h"
 
@@ -34,58 +36,61 @@ Returns:    panic on failure if panic is set; otherwise return FALSE;
 */
 
 BOOL
 */
 
 BOOL
-directory_make(const uschar *parent, const uschar *name,
+directory_make(const uschar * parent, const uschar * name,
                int mode, BOOL panic)
 {
 BOOL use_chown = parent == spool_directory && geteuid() == root_uid;
                int mode, BOOL panic)
 {
 BOOL use_chown = parent == spool_directory && geteuid() == root_uid;
-uschar *p;
-const uschar *slash;
-int c = 1;
+uschar * p;
+uschar c = 1;
 struct stat statbuf;
 struct stat statbuf;
-uschar buffer[256];
+uschar * path;
 
 
-if (parent == NULL)
+if (is_tainted(name)) 
+  { p = US"create"; path = US name; errno = ERRNO_TAINT; goto bad; }
+
+if (parent)
   {
   {
-  p = buffer + 1;
-  slash = parent = CUS"";
+  path = string_sprintf("%s%s%s", parent, US"/", name);
+  p = path + Ustrlen(parent);
   }
 else
   {
   }
 else
   {
-  p = buffer + Ustrlen(parent);
-  slash = US"/";
+  path = string_copy(name);
+  p = path + 1;
   }
 
   }
 
-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");
+/* Walk the path creating any missing directories */
 
 
-while (c != 0 && *p != 0)
+while (c && *p)
   {
   {
-  while (*p != 0 && *p != '/') p++;
+  while (*p && *p != '/') p++;
   c = *p;
   c = *p;
-  *p = 0;
-  if (Ustat(buffer, &statbuf) != 0)
+  *p = '\0';
+  if (Ustat(path, &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));
-      }
+    if (mkdir(CS path, mode) < 0 && errno != EEXIST)
+      { p = US"create"; goto bad; }
 
     /* Set the ownership if necessary. */
 
 
     /* Set the ownership if necessary. */
 
-    if (use_chown) (void)Uchown(buffer, exim_uid, exim_gid);
+    if (use_chown && exim_chown(path, exim_uid, exim_gid))
+      { p = US"set owner on"; goto bad; }
 
     /* 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. */
 
 
     /* 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) (void)Uchmod(buffer, mode);
+    if (mode & 0777000) (void) Uchmod(path, mode);
     }
   *p++ = c;
   }
 
 return TRUE;
     }
   *p++ = c;
   }
 
 return TRUE;
+
+bad:
+  if (panic) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+    "Failed to %s directory \"%s\": %s\n", p, path, exim_errstr(errno));
+  return FALSE;
 }
 
 /* End of directory.c */
 }
 
 /* End of directory.c */