[PATCH] vmailmgr 0.97 vmailmgrd "stat" command feature

Dale Woolridge <[email protected]> Sun, 11 Sep 2005 22:43:31 -0400
Newsgroups gmane.mail.vmailmgr
Message-ID <[email protected]>
--p7qwJlK53pWzbayA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

The attached patch modifies vmailmgrd's "stat" command to support
an extra parameter, the literal string "recurse", which forces
vmailmgrd to calculate the new/seen/unseen stats for all directories
and subdirectories (excluding "tmp" dirs) of the initial basedir
(virtual users homedir) instead of just the contents of new/cur
(as without the "recurse" parameter).
--
-dale

--p7qwJlK53pWzbayA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="vmailmgr-0.97-stat.recurse.dw.patch"

Index: daemon/dispatch.cc
===================================================================
--- daemon/dispatch.cc	(revision 332)
+++ daemon/dispatch.cc	(working copy)
@@ -74,7 +74,7 @@
   ENTRY(adduser3,     5, -1, true),
   ENTRY(autoresponse, 4,  5, true),
   ENTRY(deluser,      3,  3, true),
-  ENTRY(stat,         3,  3, true),
+  ENTRY(stat,         3,  4, true),
   ENTRY(listdomain,   2,  2, false),
 #ifdef TEST_DAEMON
   ENTRY(echo,         0, -1, false), // For testing purposes only
Index: daemon/stat.cc
===================================================================
--- daemon/stat.cc	(revision 332)
+++ daemon/stat.cc	(working copy)
@@ -35,7 +35,9 @@
   count_size unseen_new;
   count_size unseen;
   count_size seen;
-  
+  bool recurse;
+  unsigned long depth;
+
   mystring rep() const;
 };
 
@@ -55,6 +57,7 @@
   DIR* dir;
   struct dirent* curr;
   struct stat statbuf;
+  bool m_isdir, m_ismaildir, m_isnew, m_unseen;
 public:
   statdir(const mystring& dirname);
   ~statdir() { close(); }
@@ -65,6 +68,10 @@
   const char* currname() const { return curr->d_name; }
   void operator++() { advance(); }
   void advance();
+  bool isdir() const { return m_isdir; }
+  bool ismaildir() const { return m_ismaildir; }
+  bool isnew() const { return m_isnew; }
+  bool unseen() const { return m_unseen; }
 };
 
 statdir::statdir(const mystring& dirname)
@@ -83,12 +90,10 @@
 
 void statdir::advance()
 {
+  bool ignore = false;
+
   if(dir) {
-    while((curr = readdir(dir)) != 0) {
-      if(curr->d_name[0] == '.')
-	continue;
-      break;
-    }
+    curr = readdir(dir);
   }
   if(!curr)
     close();
@@ -96,57 +101,75 @@
     mystring fullpath = path + "/" + curr->d_name;
     if(stat(fullpath.c_str(), &statbuf) == -1)
       close();
-  }
-}
-    
-bool stat_new_dir(const mystring& basename, stats& stats)
-{
-  statdir dir(basename + "/new");
-  if(!dir)
-    return false;
-  while(dir) {
-    if(S_ISREG(dir->st_mode)) {
-      ++stats.unseen_new.count;
-      stats.unseen_new.size += dir->st_blocks * 512;
+
+    m_isdir = m_isnew = false;
+    if(S_ISDIR(statbuf.st_mode)) {
+      m_isdir = true;
+      m_isnew = !strcmp(curr->d_name, "new");
+      if(!m_isnew)
+	ignore = !strcmp(curr->d_name, ".") ||
+		 !strcmp(curr->d_name, "..") ||
+		 !strcmp(curr->d_name, "tmp");
+      m_ismaildir = m_isnew ||
+		    (!ignore && !strcmp(curr->d_name, "cur"));
+    }
+    else if(!S_ISREG(statbuf.st_mode))
+      ignore = true;
+
+    m_unseen = true;
+    const char* colon = strchr(curr->d_name, ':');
+    if(colon) {
+      ++colon;
+      if(*colon++ == '2' && *colon++ == ',' && !strchr(colon, 'S'))
+	m_unseen = false;
     }
-    ++dir;
   }
-  return true;
+  if (ignore)
+    advance();
 }
 
-bool stat_cur_dir(const mystring& basename, stats& stats)
+bool stat_dir(const mystring& basename, stats& stats, bool isnew = false)
 {
-  statdir dir(basename + "/cur");
+  statdir dir(basename);
+
   if(!dir)
-    return false;
+    return true;
+
   while(dir) {
-    if(S_ISREG(dir->st_mode)) {
-      count_size* stat = &stats.unseen;
-      const char* colon = strchr(dir.currname(), ':');
-      if(colon) {
-	++colon;
-	if(*colon++ == '2' && *colon++ == ',' && !strchr(colon, 'S'))
+    if(!dir.isdir()) {
+      count_size* stat = &stats.unseen_new;
+      if(!isnew) {
+	if (dir.unseen())
+	  stat = &stats.unseen;
+	else
 	  stat = &stats.seen;
       }
       ++stat->count;
       stat->size += dir->st_blocks * 512;
     }
+    else if(stats.recurse || (stats.depth < 1 && dir.ismaildir())) {
+      stats.depth++;
+      if (!stat_dir(basename + "/" + dir.currname(), stats, dir.isnew()))
+	return false;
+      stats.depth--;
+    }
     ++dir;
   }
   return true;
 }
 
-bool stat_dir(const mystring& basename, stats& stats)
-{
-  return stat_new_dir(basename, stats) &&
-    stat_cur_dir(basename, stats);
-}
 
 CMD(stat)
-  // Usage: stat baseuser-virtuser pass
+  // Usage: stat baseuser-virtuser pass [recurse]
 {
   mystring user = args[0];
   mystring pass = args[1];
+  args[1] = LOG_PASSWORD;
+  bool recurse = 0;
+  if(args.count() == 3) {
+    recurse = (args[2] == "recurse");
+  }
+  logcommand(args);
 
   pwentry* pw;
   vpwentry* vpw;
@@ -158,6 +181,8 @@
 
   mystring dirname = pw->home + "/" + vpw->directory;
   stats stats;
+  stats.depth = 0;
+  stats.recurse = recurse;
   if(!stat_dir(dirname, stats))
     RETURN(err, "Failed to stat maildir");
 


--p7qwJlK53pWzbayA
Content-Type: text/plain; charset=us-ascii


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
--p7qwJlK53pWzbayA--