+/*
+ * Write fdin to a new temp file in maildir/tmp, return full path to
+ * the file, or NULL on errors.
+ */
+static char *
+maildir_write_tmp (const void *ctx, int fdin, const char *maildir)
+{
+ char *path;
+ int fdout;
+
+ fdout = maildir_mktemp (ctx, maildir, &path);
+ if (fdout < 0)
+ return NULL;
+
+ if (! copy_fd (fdout, fdin))
+ goto FAIL;
+
+ if (fsync (fdout)) {
+ fprintf (stderr, "Error: fsync '%s': %s\n", path, strerror (errno));
+ goto FAIL;
+ }
+
+ close (fdout);
+
+ return path;
+
+FAIL:
+ close (fdout);
+ unlink (path);
+
+ return NULL;
+}
+
+/*
+ * Write fdin to a new file in maildir/new, using an intermediate temp
+ * file in maildir/tmp, return full path to the new file, or NULL on
+ * errors.
+ */
+static char *
+maildir_write_new (const void *ctx, int fdin, const char *maildir)
+{
+ char *cleanpath, *tmppath, *newpath, *newdir;
+
+ tmppath = maildir_write_tmp (ctx, fdin, maildir);
+ if (! tmppath)
+ return NULL;
+ cleanpath = tmppath;
+
+ newpath = talloc_strdup (ctx, tmppath);
+ if (! newpath) {
+ fprintf (stderr, "Error: %s\n", strerror (ENOMEM));
+ goto FAIL;
+ }
+
+ /* sanity checks needed? */
+ memcpy (newpath + strlen (maildir) + 1, "new", 3);
+
+ if (rename (tmppath, newpath)) {
+ fprintf (stderr, "Error: rename '%s' '%s': %s\n",
+ tmppath, newpath, strerror (errno));
+ goto FAIL;
+ }
+ cleanpath = newpath;
+
+ newdir = talloc_asprintf (ctx, "%s/%s", maildir, "new");
+ if (! newdir) {
+ fprintf (stderr, "Error: %s\n", strerror (ENOMEM));
+ goto FAIL;
+ }
+
+ if (! sync_dir (newdir))
+ goto FAIL;
+
+ return newpath;
+
+FAIL:
+ unlink (cleanpath);
+
+ return NULL;
+}
+