Here's the problem, any attempt to SETQUOTA on a mailbox
in a domain with first character of a digit, e.g.
"4demo.com", fails:

   Mar  8 00:41:14 linux imap[20406]: IOERROR: creating quota
   file /var/imap/domain/q/4demo.com/quota/s/user.someuser.NEW:
   No such file or directory

dir_hash_c is the cyrus imapd function that computes the
"q" location in that path named above:

/var/imap/domain/q/4demo.com/quota/s/user.someuser.NEW

This path *always* FAILS when using mkimap tools to
create the directories as is recommended:

mkimap -d 4demo.com

The mkimap utility in tools directory does a simple
"substr($domain, 0, 1) instead of this hash algorithm
involving special treatment of q.

One of these is clearly wrong.

Here's the perl function from the mkimap utility that
decides (incorrectly as far as I can tell) to use "4"
instead of "q" in this situation:

  sub mkdomain {
      my $domain = shift;
      my $hash = shift;

      mkdir "domain", 0755;
      chdir "domain";
      if ($hash) {
      mkdir substr($domain, 0, 1), 0755;
      chdir substr($domain, 0, 1);
      }
      mkdir "$domain", 0755;
      chdir $domain;
  }

The tools/rehash perl script already has a perl equivalent
dir_hash_c, whose relevant portion here is:

   # plb: i added next two lines, this needs to be fleshed
   # out more in mkimap, i don't know what functionality
   # the basic/full is referring to, but it seems to be in
   # the C version as well (via ifdefs), so should be here
   # too, I'd guess.
   $tofull = 0;      # HACK
   $tobasic = 1;     # HACK, force use of rehash's tobasic code.
   sub dir_hash_c {
       my $name = shift;
       my ($h, $n);

       if ($tofull) {
       $n = 0;
       foreach my $b (split(/ */, $name)) {
           $n = (($n << 3) ^ ($n >> 5)) ^ ord($b);
       }
       $h = chr(ord('A') + ($n % 23));
       return $h;
       }
       elsif ($tobasic) {
       $h = lc(substr($name, 0, 1));
       if (!($h =~ /[a-z]/)) { $h = 'q'; }
       return $h;
       }
   }

So the mkdomain function could be changed as follows to
fix the problem, simply using the above function instead
of the first char via substr:

  sub mkdomain {
      my $domain = shift;
      my $hash = shift;

      mkdir "domain", 0755;
      chdir "domain";
      if ($hash) {
      mkdir dir_hash_c($domain), 0755;
      chdir dir_hash_c($domain);
      }
      mkdir "$domain", 0755;
      chdir $domain;
  }

But as I said above, the only thing missing in this fix is
handling of the basic/full stuff.

Comments? Should I post this to the devel list?


_________________________________________________________________
STOP MORE SPAM with the new MSN 8 and get 2 months FREE* http://join.msn.com/?page=features/junkmail




Reply via email to