Intercept chown()/fchown() failure and emit a pointer to the bugreport. Closes 2391
[exim.git] / src / src / transports / appendfile.c
index ece1da51d24014dfa6673ba15017f4c698cef53b..d9f8d4989a7161763afb2090aaa92a2ae75a5e6b 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2017 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -280,7 +280,6 @@ appendfile_transport_options_block *ob =
   (appendfile_transport_options_block *)(tblock->options_block);
 uschar *q = ob->quota;
 double default_value = 0.0;
-int i;
 
 addrlist = addrlist;    /* Keep picky compilers happy */
 dummy = dummy;
@@ -294,7 +293,7 @@ if (ob->expand_maildir_use_size_file)
 /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size,
 mailbox_filecount */
 
-for (i = 0; i < 5; i++)
+for (int i = 0; i < 5; i++)
   {
   double d;
   int no_check = 0;
@@ -310,7 +309,7 @@ for (i = 0; i < 5; i++)
       {
       *errmsg = string_sprintf("Expansion of \"%s\" in %s transport failed: "
         "%s", q, tblock->name, expand_string_message);
-      return search_find_defer ? DEFER : FAIL;
+      return f.search_find_defer ? DEFER : FAIL;
       }
 
     d = Ustrtod(s, &rest);
@@ -614,7 +613,6 @@ notify_comsat(uschar *user, off_t offset)
 {
 struct servent *sp;
 host_item host;
-host_item *h;
 uschar buffer[256];
 
 DEBUG(D_transport) debug_printf("notify_comsat called\n");
@@ -648,7 +646,7 @@ if (host_find_byname(&host, NULL, 0, NULL, FALSE) == HOST_FIND_FAILED)
 host.address = US"127.0.0.1";
 
 
-for (h = &host; h; h = h->next)
+for (host_item * h = &host; h; h = h->next)
   {
   int sock, rc;
   int host_af = Ustrchr(h->address, ':') != NULL ? AF_INET6 : AF_INET;
@@ -715,8 +713,7 @@ while ((s = string_nextinlist(&format,&sep,big_buffer,big_buffer_size)))
 
   if (match && tp)
     {
-    transport_instance *tt;
-    for (tt = transports; tt; tt = tt->next)
+    for (transport_instance * tt = transports; tt; tt = tt->next)
       if (Ustrcmp(tp, tt->name) == 0)
         {
         DEBUG(D_transport)
@@ -884,10 +881,10 @@ if (dofcntl)
   {
   if (fcntltime > 0)
     {
-    alarm(fcntltime);
+    ALARM(fcntltime);
     yield = fcntl(fd, F_SETLKW, &lock_data);
     save_errno = errno;
-    alarm(0);
+    ALARM_CLR(0);
     errno = save_errno;
     }
   else yield = fcntl(fd, F_SETLK, &lock_data);
@@ -899,10 +896,10 @@ if (doflock && (yield >= 0))
   int flocktype = (fcntltype == F_WRLCK) ? LOCK_EX : LOCK_SH;
   if (flocktime > 0)
     {
-    alarm(flocktime);
+    ALARM(flocktime);
     yield = flock(fd, flocktype);
     save_errno = errno;
-    alarm(0);
+    ALARM_CLR(0);
     errno = save_errno;
     }
   else yield = flock(fd, flocktype | LOCK_NB);
@@ -945,20 +942,17 @@ copy_mbx_message(int to_fd, int from_fd, off_t saved_size)
 int used;
 off_t size;
 struct stat statbuf;
-transport_ctx tctx = {{0}};
-
-tctx.u.fd = to_fd;
+transport_ctx tctx = { .u={.fd = to_fd}, .options = topt_not_socket };
 
 /* If the current mailbox size is zero, write a header block */
 
 if (saved_size == 0)
   {
-  int i;
   uschar *s;
   memset (deliver_out_buffer, '\0', MBX_HDRSIZE);
   sprintf(CS(s = deliver_out_buffer), "*mbx*\015\012%08lx00000000\015\012",
     (long int)time(NULL));
-  for (i = 0; i < MBX_NUSERFLAGS; i++)
+  for (int i = 0; i < MBX_NUSERFLAGS; i++)
     sprintf (CS(s += Ustrlen(s)), "\015\012");
   if (!transport_write_block (&tctx, deliver_out_buffer, MBX_HDRSIZE, FALSE))
     return DEFER;
@@ -1049,10 +1043,10 @@ if (deliver_home != NULL && create_file != create_anywhere)
   #ifndef NO_REALPATH
   if (yield && create_file == create_belowhome)
     {
-    uschar *slash, *next;
+    uschar *next;
     uschar *rp = NULL;
-    for (slash = Ustrrchr(file, '/');       /* There is known to be one */
-         rp == NULL && slash > file;        /* Stop if reached beginning */
+    for (uschar * slash = Ustrrchr(file, '/');  /* There is known to be one */
+         rp == NULL && slash > file;           /* Stop if reached beginning */
          slash = next)
       {
       *slash = 0;
@@ -1380,11 +1374,8 @@ if (path[0] != '/')
 to the true local part. */
 
 if (testflag(addr, af_file))
-  {
-  address_item *addr2;
-  for (addr2 = addr; addr2 != NULL; addr2 = addr2->next)
+  for (address_item * addr2 = addr; addr2 != NULL; addr2 = addr2->next)
     addr2->local_part = string_copy(path);
-  }
 
 /* The available mailbox formats depend on whether it is a directory or a file
 delivery. */
@@ -1437,7 +1428,7 @@ DEBUG(D_transport)
 
 /* If the -N option is set, can't do any more. */
 
-if (dont_deliver)
+if (f.dont_deliver)
   {
   DEBUG(D_transport)
     debug_printf("*** delivery by %s transport bypassed by -N option\n",
@@ -1807,7 +1798,7 @@ if (!isdirectory)
       /* We have successfully created and opened the file. Ensure that the group
       and the mode are correct. */
 
-      if(Uchown(filename, uid, gid) || Uchmod(filename, mode))
+      if(exim_chown(filename, uid, gid) || Uchmod(filename, mode))
         {
         addr->basic_errno = errno;
         addr->message = string_sprintf("while setting perms on mailbox %s",
@@ -2553,7 +2544,7 @@ else
     $message_size is accurately known. */
 
     if (nametag != NULL && expand_string(nametag) == NULL &&
-        !expand_string_forcedfail)
+        !f.expand_string_forcedfail)
       {
       addr->transport_return = PANIC;
       addr->message = string_sprintf("Expansion of \"%s\" (maildir_tag "
@@ -2570,7 +2561,7 @@ else
     checked at the end, to make sure we don't release this process until the
     clock has ticked. */
 
-    for (i = 1;; i++)
+    for (int i = 1;; i++)
       {
       uschar *basename;
 
@@ -2615,7 +2606,7 @@ else
     /* Why are these here? Put in because they are present in the non-maildir
     directory case above. */
 
-    if(Uchown(filename, uid, gid) || Uchmod(filename, mode))
+    if(exim_chown(filename, uid, gid) || Uchmod(filename, mode))
       {
       addr->basic_errno = errno;
       addr->message = string_sprintf("while setting perms on maildir %s",
@@ -2636,7 +2627,6 @@ else
   else
     {
     FILE *env_file;
-    address_item *taddr;
     mailstore_basename = string_sprintf("%s/%s-%s", path, message_id,
       string_base62((long int)getpid()));
 
@@ -2662,7 +2652,7 @@ else
     /* Why are these here? Put in because they are present in the non-maildir
     directory case above. */
 
-    if(Uchown(filename, uid, gid) || Uchmod(filename, mode))
+    if(exim_chown(filename, uid, gid) || Uchmod(filename, mode))
       {
       addr->basic_errno = errno;
       addr->message = string_sprintf("while setting perms on file %s",
@@ -2690,7 +2680,7 @@ else
       uschar *s = expand_string(ob->mailstore_prefix);
       if (s == NULL)
         {
-        if (!expand_string_forcedfail)
+        if (!f.expand_string_forcedfail)
           {
           addr->transport_return = PANIC;
           addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
@@ -2711,7 +2701,7 @@ else
 
     fprintf(env_file, "%s\n", sender_address);
 
-    for (taddr = addr; taddr!= NULL; taddr = taddr->next)
+    for (address_item * taddr = addr; taddr; taddr = taddr->next)
       fprintf(env_file, "%s@%s\n", taddr->local_part, taddr->domain);
 
     if (ob->mailstore_suffix != NULL)
@@ -2719,7 +2709,7 @@ else
       uschar *s = expand_string(ob->mailstore_suffix);
       if (s == NULL)
         {
-        if (!expand_string_forcedfail)
+        if (!f.expand_string_forcedfail)
           {
           addr->transport_return = PANIC;
           addr->message = string_sprintf("Expansion of \"%s\" (mailstore "
@@ -2759,7 +2749,7 @@ else
       Uunlink(filename);
       return FALSE;
       }
-    if(Uchown(dataname, uid, gid) || Uchmod(dataname, mode))
+    if(exim_chown(dataname, uid, gid) || Uchmod(dataname, mode))
       {
       addr->basic_errno = errno;
       addr->message = string_sprintf("while setting perms on file %s",
@@ -2774,7 +2764,7 @@ else
   /* In all cases of writing to a new file, ensure that the file which is
   going to be renamed has the correct ownership and mode. */
 
-  if(Uchown(filename, uid, gid) || Uchmod(filename, mode))
+  if(exim_chown(filename, uid, gid) || Uchmod(filename, mode))
     {
     addr->basic_errno = errno;
     addr->message = string_sprintf("while setting perms on file %s",
@@ -2898,9 +2888,8 @@ if (yield == OK && ob->use_bsmtp)
     yield = DEFER;
   else
     {
-    address_item *a;
     transport_newlines++;
-    for (a = addr; a != NULL; a = a->next)
+    for (address_item * a = addr; a != NULL; a = a->next)
       {
       address_item *b = testflag(a, af_pfr) ? a->parent: a;
       if (!transport_write_string(fd, "RCPT TO:<%s>%s\n",
@@ -2921,12 +2910,12 @@ at initialization time. */
 if (yield == OK)
   {
   transport_ctx tctx = {
-    {fd},
-    tblock,
-    addr,
-    ob->check_string,
-    ob->escape_string,
-    ob->options
+    .u = {.fd=fd},
+    .tblock = tblock,
+    .addr = addr,
+    .check_string = ob->check_string,
+    .escape_string = ob->escape_string,
+    .options =  ob->options | topt_not_socket
   };
   if (!transport_write_message(&tctx, 0))
     yield = DEFER;
@@ -3082,7 +3071,7 @@ if (yield != OK)
         }
       else   /* Want a repeatable time when in test harness */
         {
-        addr->more_errno = running_in_test_harness ? 10 :
+        addr->more_errno = f.running_in_test_harness ? 10 :
           (int)time(NULL) - statbuf.st_mtime;
         }
       DEBUG(D_transport)
@@ -3241,11 +3230,10 @@ else
 
       if (newname == NULL)
         {
-        int i;
         uschar *renameleaf;
         uschar *old_renameleaf = US"";
 
-        for (i = 0; ; sleep(1), i++)
+        for (int i = 0; ; sleep(1), i++)
           {
           deliver_inode = statbuf.st_ino;
           renameleaf = expand_string(ob->dirfilename);