[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[mpop-users] [PATCH 3/9] Accept relative pathnames on exchange and maildir delivery



By internally using absolute pathnames we avoid mpop -a run trying
to access maildir/pickup dirs relative to the previous account folder.
---
 src/delivery.c | 49 ++++++++++++++++++++++++++-----------------------
 src/tools.c    | 14 ++++++++++++++
 src/tools.h    |  9 +++++++++
 3 files changed, 49 insertions(+), 23 deletions(-)

diff --git a/src/delivery.c b/src/delivery.c
index adbe8a8..d81c56a 100644
--- a/src/delivery.c
+++ b/src/delivery.c
@@ -356,10 +356,10 @@ int delivery_method_maildir_open(delivery_method_t *dm, const char *from,
     }
     /* See http://cr.yp.to/proto/maildir.html for a description of file name
      * generation. */
-    filename = xasprintf("tmp%c" PRINTFLLD ".M%06luP" PRINTFLLD "Q%lu.%s", PATH_SEP,
-                (unsigned long long)tv.tv_sec, (unsigned long)tv.tv_usec,
-                (long long)getpid(), ++maildir_sequence_number,
-                maildir_data->hostname);
+    filename = xasprintf("%stmp%c" PRINTFLLD ".M%06luP" PRINTFLLD "Q%lu.%s",
+				maildir_data->maildir, PATH_SEP, (unsigned long long)tv.tv_sec,
+				(unsigned long)tv.tv_usec, (long long)getpid(), 
+				++maildir_sequence_number, maildir_data->hostname);
     /* Instead of waiting for stat() to return ENOENT, we open() the file with
      * O_CREAT | O_EXCL. There is no point in trying again after some time,
      * because the filename is intended to be unique. If it is not, we should
@@ -367,8 +367,7 @@ int delivery_method_maildir_open(delivery_method_t *dm, const char *from,
     if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL,
                     S_IRUSR | S_IWUSR)) < 0)
     {
-        *errstr = xasprintf(_("cannot create %s%c%s: %s"),
-                maildir_data->maildir, PATH_SEP, filename, strerror(errno));
+        *errstr = xasprintf(_("cannot create %s: %s"), filename, strerror(errno));
         free(filename);
         return DELIVERY_EIO;
     }
@@ -385,7 +384,7 @@ int delivery_method_maildir_open(delivery_method_t *dm, const char *from,
 int delivery_method_maildir_close(delivery_method_t *dm, char **errstr)
 {
     maildir_data_t *maildir_data;
-    char *newfilename;
+    char *newfilename, *basename;
 
     maildir_data = dm->data;
     if (fsync(fileno(dm->pipe)) != 0)
@@ -396,17 +395,19 @@ int delivery_method_maildir_close(delivery_method_t *dm, char **errstr)
     }
     if (fclose(dm->pipe) != 0)
     {
-        *errstr = xasprintf(_("cannot close %s%c%s: %s"), maildir_data->maildir,
-                PATH_SEP, maildir_data->filename, strerror(errno));
+        *errstr = xasprintf(_("cannot close %s: %s"), 
+                maildir_data->filename, strerror(errno));
         return DELIVERY_EIO;
     }
+
     newfilename = xstrdup(maildir_data->filename);
-    strncpy(newfilename, "new", 3);
+    basename = strrchr(newfilename, PATH_SEP);
+    strncpy(basename - 3, "new", 3);
+
     if (link(maildir_data->filename, newfilename) != 0)
     {
         *errstr = xasprintf(_("%s: cannot link %s to %s: %s"),
-                maildir_data->maildir, maildir_data->filename, newfilename,
-                strerror(errno));
+                maildir_data->filename, newfilename, strerror(errno));
         free(newfilename);
         return DELIVERY_EIO;
     }
@@ -422,6 +423,7 @@ int delivery_method_maildir_init(delivery_method_t *dm, void *data,
         char **errstr)
 {
     maildir_data_t *maildir_data;
+    struct stat statdata;
     char hostname[256];
 
     maildir_data = xmalloc(sizeof(maildir_data_t));
@@ -452,9 +454,10 @@ int delivery_method_maildir_init(delivery_method_t *dm, void *data,
     dm->want_from_addr = 0;
     dm->open = delivery_method_maildir_open;
     dm->close = delivery_method_maildir_close;
-    if (chdir(maildir_data->maildir) != 0)
+    maildir_data->maildir = xastrcat(maildir_data->maildir, "/");
+    if (stat(maildir_data->maildir, &statdata) != 0)
     {
-        *errstr = xasprintf(_("cannot change to %s: %s"), maildir_data->maildir,
+        *errstr = xasprintf(_("cannot access %s: %s"), maildir_data->maildir,
                 strerror(errno));
         return DELIVERY_EUNKNOWN;
     }
@@ -515,7 +518,8 @@ int delivery_method_exchange_open(delivery_method_t *dm,
     }
     /* Choose a unique filename (similar to the maildir method) that ends with
      * ".eml" */
-    filename = xasprintf("%s-" PRINTFLLD "-M%06luP" PRINTFLLD "Q%lu-%s.eml", PACKAGE_NAME,
+    filename = xasprintf("%s%s-" PRINTFLLD "-M%06luP" PRINTFLLD "Q%lu-%s.eml", 
+				exchange_data->pickupdir, PACKAGE_NAME,
                 (long long)tv.tv_sec, (unsigned long)tv.tv_usec,
                 (long long)getpid(), ++exchange_sequence_number,
                 exchange_data->hostname);
@@ -530,16 +534,14 @@ int delivery_method_exchange_open(delivery_method_t *dm,
                     S_IRUSR | S_IWUSR)) < 0)
 #endif
     {
-        *errstr = xasprintf(_("cannot create %s%c%s: %s"),
-                exchange_data->pickupdir, PATH_SEP, filename, strerror(errno));
+        *errstr = xasprintf(_("cannot create %s%c%s: %s"), filename, strerror(errno));
         free(filename);
         return DELIVERY_EIO;
     }
     exchange_data->filename = filename;
     if (!(dm->pipe = fdopen(fd, "w")))
     {
-        *errstr = xasprintf(_("cannot open %s%c%s: %s"),
-                exchange_data->pickupdir, PATH_SEP, exchange_data->filename,
+        *errstr = xasprintf(_("cannot open %s%c%s: %s"), exchange_data->filename,
                 strerror(errno));
         return DELIVERY_EIO;
     }
@@ -549,8 +551,7 @@ int delivery_method_exchange_open(delivery_method_t *dm,
      * files (of course, they would have to obey locking for this). */
     if (lock_file(dm->pipe, TOOLS_LOCK_WRITE, 0) != 0)
     {
-        *errstr = xasprintf(_("cannot lock %s%c%s: %s"),
-                exchange_data->pickupdir, PATH_SEP, exchange_data->filename,
+        *errstr = xasprintf(_("cannot lock %s: %s"), exchange_data->filename,
                 strerror(errno));
         return DELIVERY_EIO;
     }
@@ -586,6 +587,7 @@ int delivery_method_exchange_init(delivery_method_t *dm, void *data,
         char **errstr)
 {
     exchange_data_t *exchange_data;
+    struct stat statdata;
     char hostname[256];
 
     exchange_data = xmalloc(sizeof(exchange_data_t));
@@ -616,9 +618,10 @@ int delivery_method_exchange_init(delivery_method_t *dm, void *data,
     dm->want_from_addr = 0;
     dm->open = delivery_method_exchange_open;
     dm->close = delivery_method_exchange_close;
-    if (chdir(exchange_data->pickupdir) != 0)
+    exchange_data->pickupdir = xastrcat(exchange_data->pickupdir, "/");
+    if (stat(exchange_data->pickupdir, &statdata) != 0)
     {
-        *errstr = xasprintf(_("cannot change to %s: %s"),
+        *errstr = xasprintf(_("cannot access %s: %s"),
                 exchange_data->pickupdir, strerror(errno));
         return DELIVERY_EUNKNOWN;
     }
diff --git a/src/tools.c b/src/tools.c
index df08ef6..715ab28 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -886,3 +886,17 @@ char *replace_account_variables(char *string, const account_t *account)
     free(string);
     return newstr;
 }
+
+/*
+ * xastrcat()
+ *
+ * see tools.h
+ */
+char *xastrcat(char *dest, const char *src)
+{
+    size_t dlen  = strlen(dest);
+    size_t newlen = dlen + strlen(src) + 1;
+    dest = xrealloc(dest, newlen);
+    strcat(dest + dlen, src);
+    return dest;
+}
diff --git a/src/tools.h b/src/tools.h
index c4ad3c1..cc3457b 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -213,4 +213,13 @@ char *expand_session_variables(const char *string, pop3_session_t *session,
  * character expanded, and freeing the input string.
  */
 char *replace_account_variables(char *string, const account_t *account);
+
+
+/*
+ * xastrcat()
+ * 
+ * Return a new allocated string with concatenating dest and src.
+ * The contents of dest are freed.
+ */
+char *xastrcat(char *dest, const char *src);
 #endif
-- 
2.1.1