commit-mailutils
[Top][All Lists]
Advanced

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

[SCM] GNU Mailutils branch, master, updated. release-2.2-68-gfd032c6


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-68-gfd032c6
Date: Sun, 12 Sep 2010 15:54:38 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=fd032c6f6cf30af76f67baff997367cafdacb428

The branch, master has been updated
       via  fd032c6f6cf30af76f67baff997367cafdacb428 (commit)
       via  7ebda3496ee47c3b5821375f11bd0833da2e14e4 (commit)
       via  ff95af18ea9e38cbb97b01e5ef2c8b7fcc98a132 (commit)
      from  dc0dbafe6fbd3560a4140e98777fb58bc433e92f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit fd032c6f6cf30af76f67baff997367cafdacb428
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Sep 12 18:44:59 2010 +0300

    Mailbox quota support in imap4d: initial implementation.
    
    * imap4d/quota.c: New file.
    * imap4d/Makefile.am (imap4d_SOURCES): Add quota.c
    * imap4d/append.c (imap4d_append0): Refuse to append if
    the quota is exceeded or would be exceeded after completing
    the operation.
    * imap4d/copy.c (imap4d_copy0): Refuse to copy messages if
    the quota is exceeded or would be exceeded after completing
    the operation.
    Return a meaningful textual description.
    Attempt to restore mailbox to its original size if the operation failed.
    * imap4d/imap4d.c (imap4d_session_setup0): Call quota_setup.
    * imap4d/imap4d.h (quota_setup, quota_check, quota_update): New functions.
    
    * include/mailutils/folder.h (mu_list_response) <format>: New member.
    * include/mailutils/mailbox.h (mu_mailbox_create_from_record): New
    function.
    * include/mailutils/types.hin (MU_FOLDER_ATTRIBUTE_LINK): New flag.
    * libproto/mbox/folder.c (list_helper): Do not return symbolic links
    unless MU_FOLDER_ATTRIBUTE_LINK is set.
    Fill in the resp->format member.
    * mailbox/mailbox.c (_mailbox_create_from_record): New static function.
    (_create_mailbox0): Rewrite as a wrapper over _mailbox_create_from_record.
    (mu_mailbox_create_from_record): New function.

commit 7ebda3496ee47c3b5821375f11bd0833da2e14e4
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Sep 12 18:42:49 2010 +0300

    movemail: bugfix.
    
    * movemail/movemail.c (guess_mbox_owner): Fix setting GID
    with --owner=set-id.
    (main): Don't attempt to expunge source mailbox if preserve_mail
    is set.

commit ff95af18ea9e38cbb97b01e5ef2c8b7fcc98a132
Author: Sergey Poznyakoff <address@hidden>
Date:   Sun Sep 12 18:42:02 2010 +0300

    amd: bugfix.
    
    * mailbox/amd.c (read_size_file): Fix return value.

-----------------------------------------------------------------------

Summary of changes:
 imap4d/Makefile.am          |    1 +
 imap4d/append.c             |   48 ++++++++---
 imap4d/copy.c               |  172 ++++++++++++++++++++++++++++++++++---
 imap4d/imap4d.c             |    5 +
 imap4d/imap4d.h             |    7 ++-
 imap4d/quota.c              |  203 +++++++++++++++++++++++++++++++++++++++++++
 include/mailutils/folder.h  |    1 +
 include/mailutils/mailbox.h |    5 +-
 include/mailutils/types.hin |    5 +-
 libproto/mbox/folder.c      |    7 +-
 mailbox/amd.c               |    2 +
 mailbox/mailbox.c           |  188 +++++++++++++++++++++++-----------------
 movemail/movemail.c         |    4 +-
 13 files changed, 538 insertions(+), 110 deletions(-)
 create mode 100644 imap4d/quota.c

diff --git a/imap4d/Makefile.am b/imap4d/Makefile.am
index bb0c19b..a0bd98b 100644
--- a/imap4d/Makefile.am
+++ b/imap4d/Makefile.am
@@ -50,6 +50,7 @@ imap4d_SOURCES = \
  noop.c\
  parsebuf.c\
  preauth.c\
+ quota.c\
  rename.c\
  search.c\
  select.c\
diff --git a/imap4d/append.c b/imap4d/append.c
index 3a5c6cc..bf126b8 100644
--- a/imap4d/append.c
+++ b/imap4d/append.c
@@ -71,10 +71,11 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char 
*date_time, char *text,
   struct tm *tm;
   time_t t;
   mu_envelope_t env;
-    
+  size_t size;
+  
   if (mu_message_create (&msg, &tm))
     return 1;
-  
+
   if (mu_memory_stream_create (&stream, MU_STREAM_RDWR)
       || mu_stream_open (stream))
     {
@@ -94,9 +95,9 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char 
*date_time, char *text,
        }
     }
   else
-    time(&t);
+    time (&t);
   
-  tm = gmtime(&t);
+  tm = gmtime (&t);
 
   while (*text && mu_isblank (*text))
     text++;
@@ -109,15 +110,40 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char 
*date_time, char *text,
   mu_envelope_set_date (env, _append_date, msg);
   mu_envelope_set_sender (env, _append_sender, msg);
   mu_message_set_envelope (msg, env, &tm);
+
+  rc = _append_size (msg, &size);
+  if (rc)
+    {
+      mu_diag_output (MU_DIAG_NOTICE,
+                     _("cannot compute size of the message being appended; "
+                       "using estimated value: %s"),
+                     mu_strerror (rc));
+      /* raw estimate */
+      size = strlen (text);
+    }
+  rc = quota_check (size);
+  if (rc != RESP_OK)
+    {
+      *err_text = rc == RESP_NO ?
+                          "Mailbox quota exceeded" : "Operation failed";
+      mu_message_destroy (&msg, &tm);
+      return 1;
+    }
+  
   rc = mu_mailbox_append_message (mbox, msg);
-  if (rc == 0 && flags)
+  if (rc == 0)
     {
-      size_t num = 0;
-      mu_attribute_t attr = NULL;
-      mu_mailbox_messages_count (mbox, &num);
-      mu_mailbox_get_message (mbox, num, &msg);
-      mu_message_get_attribute (msg, &attr);
-      mu_attribute_set_flags (attr, flags);
+      if (flags)
+       {
+         size_t num = 0;
+         mu_attribute_t attr = NULL;
+         mu_mailbox_messages_count (mbox, &num);
+         mu_mailbox_get_message (mbox, num, &msg);
+         mu_message_get_attribute (msg, &attr);
+         mu_attribute_set_flags (attr, flags);
+       }
+      /* FIXME: If not INBOX */
+      quota_update (size);
     }
 
   mu_message_destroy (&msg, &tm);
diff --git a/imap4d/copy.c b/imap4d/copy.c
index ef7aea0..ad61fb3 100644
--- a/imap4d/copy.c
+++ b/imap4d/copy.c
@@ -57,6 +57,153 @@ imap4d_copy (struct imap4d_command *command, 
imap4d_tokbuf_t tok)
   return io_completion_response (command, rc, "%s", text);
 }
 
+static int
+copy_check_size (mu_mailbox_t mbox, size_t n, size_t *set, mu_off_t *size)
+{
+  int status;
+  size_t i;
+  mu_off_t total = 0;
+  
+  for (i = 0; i < n; i++)
+    {
+      mu_message_t msg = NULL;
+      size_t msgno = set[i];
+      if (msgno)
+       {
+         status = mu_mailbox_get_message (mbox, msgno, &msg);
+         if (status)
+           {
+             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
+                              status);
+             return RESP_BAD;
+           }
+         else 
+           {
+             size_t size;
+             status = mu_message_size (msg, &size);
+             if (status)
+               {
+                 mu_diag_funcall (MU_DIAG_ERROR, "mu_message_size", NULL,
+                                  status);
+                 return RESP_BAD;
+               }
+             total += size;
+           }
+       }
+    }
+  *size = total;
+  return quota_check (total);
+}
+
+static int
+try_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set)
+{
+  int result;
+  size_t i;
+  mu_off_t total;
+  
+  result = copy_check_size (src, n, set, &total);
+  if (result)
+    return result;
+  
+  for (i = 0; i < n; i++)
+    {
+      mu_message_t msg = NULL;
+      size_t msgno = set[i];
+
+      if (msgno)
+       {
+         int status = mu_mailbox_get_message (src, msgno, &msg);
+         if (status)
+           {
+             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_message", NULL,
+                              status);
+             return RESP_BAD;
+           }
+
+         status = mu_mailbox_append_message (dst, msg);
+         if (status)
+           {
+             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_append_message",
+                              NULL,
+                              status);
+             return RESP_BAD;
+           }
+       }
+    }
+  quota_update (total);
+  return RESP_OK;
+}
+
+static int
+safe_copy (mu_mailbox_t dst, mu_mailbox_t src, size_t n, size_t *set,
+          char **err_text)
+{
+  size_t nmesg;
+  int status;
+  
+  status = mu_mailbox_messages_count (dst, &nmesg);
+  if (status)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_messages_count",
+                      NULL, status);
+      *err_text = "Operation failed";
+      return RESP_NO;
+    }
+
+  status = try_copy (dst, src, n, set);
+  if (status)
+    {
+      size_t maxmesg;
+
+      if (status == RESP_NO)
+       *err_text = "Mailbox quota exceeded";
+      else
+       *err_text = "Operation failed";
+      
+      /* If the COPY command is unsuccessful for any reason, server
+        implementations MUST restore the destination mailbox to its state
+        before the COPY attempt. */
+
+      status = mu_mailbox_messages_count (dst, &maxmesg);
+      if (status)
+       {
+         mu_url_t url = NULL;
+
+         mu_mailbox_get_url (dst, &url);
+         mu_error (_("cannot count messages in mailbox %s: %s"),
+                   mu_url_to_string (url), mu_strerror (status));
+         imap4d_bye (ERR_MAILBOX_CORRUPTED);
+       }
+      
+      for (nmesg++; nmesg <= maxmesg; nmesg++)
+       {
+         mu_message_t msg;
+         
+         if (mu_mailbox_get_message (dst, nmesg, &msg) == 0)
+           {
+             mu_attribute_t attr;
+             mu_message_get_attribute (msg, &attr);
+             mu_attribute_set_userflag (attr, MU_ATTRIBUTE_DELETED);
+           }
+       }
+      
+      status = mu_mailbox_flush (dst, 1);
+      if (status)
+       {
+         mu_url_t url = NULL;
+
+         mu_mailbox_get_url (dst, &url);
+         mu_error (_("cannot flush mailbox %s: %s"),
+                   mu_url_to_string (url), mu_strerror (status));
+         imap4d_bye (ERR_MAILBOX_CORRUPTED);
+       }
+      return RESP_NO;
+    }
+  
+  return RESP_OK;
+}
+
 int
 imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
 {
@@ -70,7 +217,8 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
   mu_mailbox_t cmbox = NULL;
   int arg = IMAP4_ARG_1 + !!isuid;
   int ns;
-  
+
+  *err_text = NULL;
   if (imap4d_tokbuf_argc (tok) != arg + 2)
     {
       *err_text = "Invalid arguments";
@@ -89,11 +237,19 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
       return RESP_OK;
     }
 
+  if (isuid)
+    {
+      int i;
+      /* Fixup the message set. Perhaps util_msgset should do it itself? */
+      for (i = 0; i < n; i++)
+       set[i] = uid_to_msgno (set[i]);
+    }
+  
   mailbox_name = namespace_getfullpath (name, delim, &ns);
 
   if (!mailbox_name)
     {
-      *err_text = "NO Copy failed.";
+      *err_text = "Copy failed";
       return RESP_NO;
     }
 
@@ -106,14 +262,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
       status = mu_mailbox_open (cmbox, MU_STREAM_RDWR | mailbox_mode[ns]);
       if (status == 0)
        {
-         size_t i;
-         for (i = 0; i < n; i++)
-           {
-             mu_message_t msg = NULL;
-             size_t msgno = (isuid) ? uid_to_msgno (set[i]) : set[i];
-             if (msgno && mu_mailbox_get_message (mbox, msgno, &msg) == 0)
-               mu_mailbox_append_message (cmbox, msg);
-           }
+         status = safe_copy (cmbox, mbox, n, set, err_text);
          mu_mailbox_close (cmbox);
        }
       mu_mailbox_destroy (&cmbox);
@@ -132,6 +281,7 @@ imap4d_copy0 (imap4d_tokbuf_t tok, int isuid, char 
**err_text)
      of the text of the tagged NO response.  This gives a hint to the
      client that it can attempt a CREATE command and retry the copy if
      the CREATE is successful.  */
-  *err_text = "[TRYCREATE] failed";
+  if (!*err_text)
+    *err_text = "[TRYCREATE] failed";
   return RESP_NO;
 }
diff --git a/imap4d/imap4d.c b/imap4d/imap4d.c
index a5b29e0..0c65ec2 100644
--- a/imap4d/imap4d.c
+++ b/imap4d/imap4d.c
@@ -352,9 +352,14 @@ imap4d_session_setup0 ()
 
   util_chdir (imap4d_homedir);
   namespace_init_session (imap4d_homedir);
+  
   mu_diag_output (MU_DIAG_INFO,
                  _("user `%s' logged in (source: %s)"), auth_data->name,
                  auth_data->source);
+
+  if (auth_data->quota)
+    quota_setup ();
+  
   return 0;
 }
 
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index 7618107..612505e 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -423,7 +423,12 @@ extern void auth_gsasl_init (void);
 #else
 # define auth_gsasl_init()
 #endif
-  
+
+/* Quota support */
+void quota_setup (void);
+int quota_check (mu_off_t size);
+void quota_update (mu_off_t size);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/imap4d/quota.c b/imap4d/quota.c
new file mode 100644
index 0000000..b39f0d8
--- /dev/null
+++ b/imap4d/quota.c
@@ -0,0 +1,203 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+   2009, 2010 Free Software Foundation, Inc.
+
+   GNU Mailutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mailutils is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include "imap4d.h"
+
+struct imap4d_sizeinfo
+{
+  mu_off_t size;
+  mu_off_t nfiles;
+  mu_off_t ndirs;
+  mu_off_t nerrs;
+};
+  
+static int
+addsize (mu_folder_t folder, struct mu_list_response *resp, void *data)
+{
+  struct imap4d_sizeinfo *si = data;
+
+  if (resp->type & MU_FOLDER_ATTRIBUTE_DIRECTORY)
+    si->ndirs++;
+  
+  if (resp->type & MU_FOLDER_ATTRIBUTE_FILE)
+    {
+      mu_off_t size;
+      mu_mailbox_t mbox;
+      int rc;
+      
+      si->nfiles++;
+
+      rc = mu_mailbox_create_from_record (&mbox, resp->format, resp->name);
+
+      if (rc)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_from_record",
+                          resp->name, rc);
+         si->nerrs++;
+         return 0;
+       }
+
+      rc = mu_mailbox_open (mbox, MU_STREAM_READ);
+      if (rc)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open",
+                          resp->name, rc);
+         si->nerrs++;
+         mu_mailbox_destroy (&mbox);
+         return 0;
+       }
+
+      rc = mu_mailbox_get_size (mbox, &size);
+      mu_mailbox_destroy (&mbox);
+
+      if (rc)
+       {
+         mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open",
+                          resp->name, rc);
+         si->nerrs++;
+         return 0;
+       }
+      si->size += size;
+    }
+  return 0;
+}
+  
+void
+directory_size (const char *dirname, mu_off_t *size)
+{
+  mu_folder_t folder;
+  struct imap4d_sizeinfo sizeinfo;
+  int status;
+  
+  status = mu_folder_create (&folder, dirname);
+  if (status)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", dirname, status);
+      return;
+    }
+
+  status = mu_folder_open (folder, MU_STREAM_READ);
+  if (status)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", dirname, status);
+      mu_folder_destroy (&folder);
+      return;
+    }
+
+  memset (&sizeinfo, 0, sizeof (sizeinfo));
+  status = mu_folder_enumerate (folder, NULL, "*", 0, 0, NULL,
+                               addsize, &sizeinfo);
+  if (status)
+    mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_enumerate", dirname, status);
+  else
+    {
+      mu_diag_output (MU_DIAG_INFO,
+                     _("%s statistics: size=%lu, ndirs=%lu, nfiles=%lu, 
nerrs=%lu"),
+                     dirname,
+                     (unsigned long)sizeinfo.size,
+                     (unsigned long)sizeinfo.ndirs,
+                     (unsigned long)sizeinfo.nfiles,
+                     (unsigned long)sizeinfo.nerrs);
+    }
+  *size = sizeinfo.size;
+}
+
+
+mu_off_t used_size;
+
+void
+quota_setup ()
+{
+  directory_size (imap4d_homedir, &used_size);
+}
+
+int
+quota_check (mu_off_t size)
+{
+  char *mailbox_name;
+  mu_mailbox_t mbox;
+  mu_off_t total;
+  int rc;
+  
+  if (auth_data->quota == 0)
+    return RESP_OK;
+
+  total = used_size;
+
+  mailbox_name = namespace_getfullpath ("INBOX", "/", NULL);
+  rc = mu_mailbox_create (&mbox, mailbox_name);
+  if (rc)
+    {
+      mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create", mailbox_name, rc);
+      free (mailbox_name);
+    }
+  else
+    {
+      do
+       {
+         mu_off_t mbsize;
+         
+         rc = mu_mailbox_open (mbox, MU_STREAM_READ);
+         if (rc)
+           {
+             if (rc != ENOENT)
+               mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_open",
+                                mailbox_name, rc);
+             break;
+           }
+         
+         rc = mu_mailbox_get_size (mbox, &mbsize);
+         if (rc)
+           {
+             mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_get_size",
+                              mailbox_name, rc);
+             mu_mailbox_close (mbox);
+             break;
+           }
+         total += mbsize;
+         mu_mailbox_close (mbox);
+       }
+      while (0);
+      mu_mailbox_destroy (&mbox);
+    }
+  free (mailbox_name);
+
+  if (rc)
+    return RESP_BAD;
+  
+  if (total > auth_data->quota)
+    {
+      mu_diag_output (MU_DIAG_NOTICE,
+                     _("user %s is out of mailbox quota"),
+                     auth_data->name);
+      return RESP_NO;
+    }
+  else if (total + size > auth_data->quota)
+    {
+      mu_diag_output (MU_DIAG_NOTICE,
+                     _("user %s: adding %lu bytes would exceed mailbox quota"),
+                     auth_data->name, (unsigned long) size);
+      return RESP_NO;
+    }
+  return RESP_OK;
+}
+
+void
+quota_update (mu_off_t size)
+{
+  used_size += size;
+}
diff --git a/include/mailutils/folder.h b/include/mailutils/folder.h
index 279c80f..b16dc47 100644
--- a/include/mailutils/folder.h
+++ b/include/mailutils/folder.h
@@ -32,6 +32,7 @@ struct mu_list_response
   int level;
   int separator;
   char *name;
+  mu_record_t format;   /* Associated mailbox format record */
 };
 
 typedef int (*mu_folder_match_fp) (const char *, void *, int);
diff --git a/include/mailutils/mailbox.h b/include/mailutils/mailbox.h
index bec4498..1d1ce96 100644
--- a/include/mailutils/mailbox.h
+++ b/include/mailutils/mailbox.h
@@ -40,9 +40,12 @@ int mu_construct_user_mailbox_url (char **pout, const char 
*name);
 /* Constructor/destructor and possible types.  */
 extern int  mu_mailbox_create          (mu_mailbox_t *, const char *);
 extern int  mu_mailbox_create_from_url (mu_mailbox_t *, mu_url_t);
+extern int  mu_mailbox_create_from_record (mu_mailbox_t *pmbox,
+                                          mu_record_t record,
+                                          const char *name);
+extern int  mu_mailbox_create_default  (mu_mailbox_t *, const char *);
 
 extern void mu_mailbox_destroy         (mu_mailbox_t *);
-extern int  mu_mailbox_create_default  (mu_mailbox_t *, const char *);
 
 extern int  mu_mailbox_open            (mu_mailbox_t, int flag);
 extern int  mu_mailbox_close           (mu_mailbox_t);
diff --git a/include/mailutils/types.hin b/include/mailutils/types.hin
index c492a5c..5917c7f 100644
--- a/include/mailutils/types.hin
+++ b/include/mailutils/types.hin
@@ -118,8 +118,9 @@ typedef struct _mu_progmailer *mu_progmailer_t;
 typedef struct _mu_secret *mu_secret_t;
 typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t;
   
-#define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
-#define MU_FOLDER_ATTRIBUTE_FILE      0x002
+#define MU_FOLDER_ATTRIBUTE_DIRECTORY  0x001
+#define MU_FOLDER_ATTRIBUTE_FILE       0x002
+#define MU_FOLDER_ATTRIBUTE_LINK       0x004
 
 #define MU_FOLDER_ATTRIBUTE_ALL \
           (MU_FOLDER_ATTRIBUTE_DIRECTORY|MU_FOLDER_ATTRIBUTE_FILE)
diff --git a/libproto/mbox/folder.c b/libproto/mbox/folder.c
index 0c44323..4ae658b 100644
--- a/libproto/mbox/folder.c
+++ b/libproto/mbox/folder.c
@@ -315,7 +315,7 @@ list_helper (struct search_data *data, mu_record_t record,
   DIR *dirp;
   struct dirent *dp;
   int stop = 0;
-  
+    
   if (data->max_level && level > data->max_level)
     return 0;
 
@@ -345,13 +345,15 @@ list_helper (struct search_data *data, mu_record_t record,
       if (ename[ename[0] != '.' ? 0 : ename[1] != '.' ? 1 : 2] == 0)
        continue;
       fname = get_pathname (dirname, ename);
-      if (stat (fname, &st) == 0)
+      if (lstat (fname, &st) == 0)
        {
          int f;
          if (S_ISDIR (st.st_mode))
            f = MU_FOLDER_ATTRIBUTE_DIRECTORY;
          else if (S_ISREG (st.st_mode))
            f = MU_FOLDER_ATTRIBUTE_FILE;
+         else if (S_ISLNK (st.st_mode))
+           f = MU_FOLDER_ATTRIBUTE_LINK;
          else
            f = 0;
          if (mu_record_list_p (record, ename, f))
@@ -386,6 +388,7 @@ list_helper (struct search_data *data, mu_record_t record,
                  resp->level = level;
                  resp->separator = '/';
                  resp->type = type;
+                 resp->format = rec;
                  
                  if (resp->type == 0)
                    {
diff --git a/mailbox/amd.c b/mailbox/amd.c
index eaa20d4..3cf3dde 100644
--- a/mailbox/amd.c
+++ b/mailbox/amd.c
@@ -1005,6 +1005,8 @@ read_size_file (struct _amd_data *amd, mu_off_t *psize)
        rc = 1;
       fclose (fp);
     }
+  else
+    rc = 1;
   free (name);
   return rc;
 }
diff --git a/mailbox/mailbox.c b/mailbox/mailbox.c
index e7c0dcc..e1c7b59 100644
--- a/mailbox/mailbox.c
+++ b/mailbox/mailbox.c
@@ -69,102 +69,110 @@ mailbox_folder_create (mu_mailbox_t mbox, const char 
*name,
   return rc;
 }
 
-static int
-_create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
+int
+_mailbox_create_from_record (mu_mailbox_t *pmbox,
+                            mu_record_t record,
+                            mu_url_t url, 
+                            const char *name)
 {
-  int status;
-  mu_record_t record = NULL;
-
-  if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
-      == 0)
+  mu_log_level_t level;
+  int (*m_init) (mu_mailbox_t) = NULL;
+      
+  mu_record_get_mailbox (record, &m_init);
+  if (m_init)
     {
-      mu_log_level_t level;
-      int (*m_init) (mu_mailbox_t) = NULL;
+      int status;
+      int (*u_init) (mu_url_t) = NULL;
+      mu_mailbox_t mbox;
       
-      mu_record_get_mailbox (record, &m_init);
-      if (m_init)
-        {
-         int (*u_init) (mu_url_t) = NULL;
-         mu_mailbox_t mbox;
-
-         /* Allocate memory for mbox.  */
-         mbox = calloc (1, sizeof (*mbox));
-         if (mbox == NULL)
-           return ENOMEM;
-
-         /* Initialize the internal lock now, so the concrete mailbox
-            could use it. */
-         status = mu_monitor_create (&mbox->monitor, 0, mbox);
-         if (status != 0)
-           {
-             mu_mailbox_destroy (&mbox);
-             return status;
-           }
-
-         /* Make sure scheme contains actual mailbox scheme */
-         /* FIXME: It is appropriate not for all record types.  For now we
-            assume that if the record scheme ends with a plus sign, this
-            should not be done.  Probably it requires some flag in struct
-            _mu_record? */
-         if (strcmp (url->scheme, record->scheme))
-           {
-             char *p = strdup (record->scheme);
-             if (!p)
-               {
-                 mu_mailbox_destroy (&mbox);
-                 return errno;
-               }
-             free (url->scheme);
-             url->scheme = p;
-           }
-
-         mu_record_get_url (record, &u_init);
-         if (u_init && (status = u_init (url)) != 0)
+      /* Allocate memory for mbox.  */
+      mbox = calloc (1, sizeof (*mbox));
+      if (mbox == NULL)
+       return ENOMEM;
+      
+      /* Initialize the internal lock now, so the concrete mailbox
+        could use it. */
+      status = mu_monitor_create (&mbox->monitor, 0, mbox);
+      if (status != 0)
+       {
+         mu_mailbox_destroy (&mbox);
+         return status;
+       }
+      
+      /* Make sure scheme contains actual mailbox scheme */
+      /* FIXME: It is appropriate not for all record types.  For now we
+        assume that if the record scheme ends with a plus sign, this
+        should not be done.  Probably it requires some flag in struct
+        _mu_record? */
+      if (strcmp (url->scheme, record->scheme))
+       {
+         char *p = strdup (record->scheme);
+         if (!p)
            {
              mu_mailbox_destroy (&mbox);
-             return status;
+             return errno;
            }
-
-         mbox->url = url;
-
-         /* Create the folder before initializing the concrete mailbox.
-            The mailbox needs it's back pointer. */
-         status = mailbox_folder_create (mbox, name, record);
+         free (url->scheme);
+         url->scheme = p;
+       }
+      
+      mu_record_get_url (record, &u_init);
+      if (u_init && (status = u_init (url)) != 0)
+       {
+         mu_mailbox_destroy (&mbox);
+         return status;
+       }
+      
+      mbox->url = url;
+      
+      /* Create the folder before initializing the concrete mailbox.
+        The mailbox needs it's back pointer. */
+      status = mailbox_folder_create (mbox, name, record);
+      
+      if (status == 0)
+       status = m_init (mbox);   /* Create the concrete mailbox type.  */
+      
+      if (status != 0)
+       {
+         /* Take care not to destroy url.  Leave it to caller. */
+         mbox->url = NULL;
+         mu_mailbox_destroy (&mbox);
+       }
+      else
+       {
+         *pmbox = mbox;
          
-         if (status == 0)
-           status = m_init (mbox);   /* Create the concrete mailbox type.  */
-
-         if (status != 0)
-           {
-             /* Take care not to destroy url.  Leave it to caller. */
-             mbox->url = NULL;
-             mu_mailbox_destroy (&mbox);
-           }
-         else
+         level = mu_global_debug_level ("mailbox");
+         if (level)
            {
-             *pmbox = mbox;
-
-             level = mu_global_debug_level ("mailbox");
-             if (level)
-               {
-                 int status = mu_debug_create (&mbox->debug, mbox);
-                 if (status)
-                   return 0; /* FIXME: don't want to bail out just because I
-                                failed to create a *debug* object. But I may
-                                be wrong... */
-                 mu_debug_set_level (mbox->debug, level);
-                 if (level & MU_DEBUG_INHERIT)
-                   mu_folder_set_debug (mbox->folder, mbox->debug);
-               }
+             int status = mu_debug_create (&mbox->debug, mbox);
+             if (status)
+               return 0; /* FIXME: don't want to bail out just because I
+                            failed to create a *debug* object. But I may
+                            be wrong... */
+             mu_debug_set_level (mbox->debug, level);
+             if (level & MU_DEBUG_INHERIT)
+               mu_folder_set_debug (mbox->folder, mbox->debug);
            }
-         
-         return status;
        }
+      
+      return status;
     }
   return MU_ERR_NO_HANDLER;
 }
 
 static int
+_create_mailbox0 (mu_mailbox_t *pmbox, mu_url_t url, const char *name)
+{
+  mu_record_t record = NULL;
+
+  if (mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_FILE, &record, NULL)
+      == 0)
+    return _mailbox_create_from_record (pmbox, record, url, name);
+  return MU_ERR_NO_HANDLER;
+}
+
+static int
 _create_mailbox (mu_mailbox_t *pmbox, const char *name)
 {
   int status;
@@ -202,6 +210,24 @@ mu_mailbox_create_from_url (mu_mailbox_t *pmbox, mu_url_t 
url)
   return _create_mailbox0 (pmbox, url, mu_url_to_string (url));
 }
 
+int
+mu_mailbox_create_from_record (mu_mailbox_t *pmbox, mu_record_t record,
+                              const char *name)
+{
+  mu_url_t url;
+  int rc;
+  
+  rc = mu_url_create (&url, name);
+  if (rc)
+    return rc;
+  rc = mu_url_parse (url);
+  if (rc == 0)
+    rc = _mailbox_create_from_record (pmbox, record, url, name);
+  if (rc)
+    mu_url_destroy (&url);
+  return rc;
+}
+
 void
 mu_mailbox_destroy (mu_mailbox_t *pmbox)
 {
diff --git a/movemail/movemail.c b/movemail/movemail.c
index 9bc8d18..985242f 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -606,6 +606,8 @@ guess_mbox_owner (mu_mailbox_t mbox, struct user_id *id)
                  rc = 1;
                }
            }
+         else
+           id->gid = meth->owner.id.gid;
          break;
          
        case set_owner_name:
@@ -891,7 +893,7 @@ main (int argc, char **argv)
   mu_mailbox_destroy (&dest);
   if (rc)
     mu_error (_("cannot close destination mailbox: %s"), mu_strerror (rc));
-  else
+  else if (!preserve_mail)
     mu_mailbox_flush (source, 1);
 
   mu_mailbox_close (source);


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]