Codebase list cyrus-imapd / 62324ae
Imported Upstream version 2.4.15 Ondřej Surý 12 years ago
68 changed file(s) with 661 addition(s) and 788 deletion(s). Raw diff Collapse all Expand all
6363 COMPILE_ET = @COMPILE_ET@
6464
6565 PACKAGE = cyrus-imapd
66 VERSION = 2.4.14
66 VERSION = 2.4.15
6767 GIT_VERSION = $(VERSION).git$(shell date +'%Y%m%d%H%M')
6868
6969 all:: xversion
77 </head>
88 <body>
99
10 <h1>Changes to the Cyrus IMAP Server since 2.4.14</h1>
11 <ul>
12 <li>Bug #3664, #3665 - Sieve filters don't work if mailbox contains dots</li>
13 <li>Bug #3651 - 64 bit dirhash breaks existing systems. NOTE - this includes a complete
14 rewrite of tools/rehash, making it much simpler and more reliable. Check the usage
15 statement</li>
16 <li>Bug #1228 - mailbox dumps need to dump quotaroots</li>
17 <li>Bug #3613 - CATENATE command returns BADURL</li>
18 <li>Bug #3627 - enabling improved_mboxlist_sort documentation mention subscription files</li>
19 <li>Bug #3661 - Memory leaks in sync_server, nntpd, popd</li>
20 <li>Bug #3621 - quota bug involving nested quota roots</li>
21 <li>Bug #3667 - FLAGS.SILENT needs to return new MODSEQ if QRESYNC enabled</li>
22 </ul>
23
24 <h1>Changes to the Cyrus IMAP Server since 2.4.13</h1>
25 <ul>
26 <li>Bug #2685 - folder delete and annotations</li>
27 <li>Bug #3381 - tools/rehash script is not 64bit safe</li>
28 <li>Bug #3405 - Cyrus IMAP tls support for ctl_mboxlist</li>
29 <li>Bug #3485 - cyr_expire tries to delete parent directories that are not empty</li>
30 <li>Bug #3582 - Extra LF+SP characters been inserted in the middle of the XML attachments</li>
31 <li>Bug #3598 - lmtp auditlog for murder proxy mode</li>
32 <li>Bug #3623 - OpenBSD (and other platforms without working mmap) multiple bugs</li>
33 <li>Bug #3626 - Renaming a mailbox doesn't remove old folder</li>
34 <li>Bug #3628 - folders with spaces and subfolders with same prefix as parent folder don't show up</li>
35 <li>Bug #3634 - RENAME INBOX no longer works</li>
36 <li>Bug #3635 - cmd_rename() fails to check error codes</li>
37 <li>Bug #3636 - unexpunge locks mailbox until all output is emitted</li>
38 <li>Bug #3637 - imapd and ipop3d in 2.4 no longer log expunge events to syslog</li>
39 <li>Bug #3638 - sessionid logging improvements for murder environments</li>
40 <li>Bug #3640 - LMTP accepts NULL bytes in headers, resulting in incorrect header/mail size in meta-data</li>
41 <li>Bug #3642 - iPhone 5 expects SPECIAL-USE in LIST output</li>
42 <li>Bug #3649 - unable to remove mailbox</li>
43 <li>Bug #3650 - ENVELOPE contains unexpected CRLF</li>
44 <li>Bug #3645 - Ability to delete folder "shared"</li>
45 </ul>
1046
1147 <h1>Changes to the Cyrus IMAP Server since 2.4.12</h1>
1248 <ul>
66 <body>
77
88 <h1>Upgrading From Previous Versions</h1>
9
10 <h2>Upgrading from 2.4.14</h2>
11 <ul>
12 <li>We recommend that ALL sites with fulldirhash enabled run
13 tools/rehash on their mail spools after upgrading from
14 2.4.14. There were serious 32 vs 64 bit hashing bugs
15 which were made worse with 2.4.14. NOTE: the syntax of
16 tools/rehash has changed. Run it without arguments to
17 see a usage statement.</li>
18 </ul>
919
1020 <h2>Upgrading from 2.4.12</h2>
1121 <ul>
0 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <title>Enabling improved_mboxlist_sort</title>
5 </head>
6 <body>
7 <H1>Enabling improved_mboxlist_sort</H1>
8
9 <p>You can't enable and disable improved_mboxlist_sort on a live
10 system. You need to dump and load the necessary database after
11 stopping and before starting the master process.<p>
12
13 <p>Dumping the mailboxes.db file</p>
14 <pre>
15 ctl_mboxlist -d > /var/tmp/mailboxes.txt
16 ctl_mboxlist -u < /var/tmp/mailboxes.txt
17 </pre>
18
19 <p>If your subscription databases are not in flat files you need to do
20 something similar. Each user will have his own subscription file. Do
21 the following for each subscription file.</p>
22
23 <pre>
24 cyr_dbtool -C $file skiplist show > $file.TXT
25 cyr_dbtool -n $file skiplist set < $file.TXT
26 </pre>
27
28 <p>The above fragments will overwrite the original file. So you could
29 redirect to a temporary file and overwrite the database if the import
30 succeeds.</p>
31
32 </body>
33 </html>
4747
4848 <li><a href="specials.html">Special Characters</a></li>
4949
50 <li><a href="improved_mboxlist_sort.html">Enabling improved_mboxlist_sort</a></li>
51
5052 </body>
5153 </html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:30 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:05 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:05 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:05 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:05 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:31 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:06 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
660660
661661 <p style="margin-left:11%; margin-top: 1em">Note that this
662662 option SHOULD NOT be changed on a live system. The mailboxes
663 database should be dumped before the option is changed,
664 removed, and then undumped after changing the option.
663 database should be dumped (ctl_mboxlist) before the option
664 is changed, removed, and then undumped after changing the
665 option. When not using flat files for the subscriptions
666 databases the same has to be done (cyr_dbtool) for each
667 subscription database See improved_mboxlist_sort.html.
665668 <b><br>
666669 internaldate_heuristic:</b> standard</p>
667670
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:32 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:07 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:33 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:08 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
00 <!-- Creator : groff version 1.21 -->
1 <!-- CreationDate: Mon Mar 12 11:59:34 2012 -->
1 <!-- CreationDate: Wed Apr 18 12:30:09 2012 -->
22 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
33 "http://www.w3.org/TR/html4/loose.dtd">
44 <html>
0 Changes to the Cyrus IMAP Server since 2.4.14
1
2 * Bug #3664, #3665 - Sieve filters don't work if mailbox contains
3 dots
4 * Bug #3651 - 64 bit dirhash breaks existing systems. NOTE - this
5 includes a complete rewrite of tools/rehash, making it much simpler
6 and more reliable. Check the usage statement
7 * Bug #1228 - mailbox dumps need to dump quotaroots
8 * Bug #3613 - CATENATE command returns BADURL
9 * Bug #3627 - enabling improved_mboxlist_sort documentation mention
10 subscription files
11 * Bug #3661 - Memory leaks in sync_server, nntpd, popd
12 * Bug #3621 - quota bug involving nested quota roots
13 * Bug #3667 - FLAGS.SILENT needs to return new MODSEQ if QRESYNC
14 enabled
15
16 Changes to the Cyrus IMAP Server since 2.4.13
17
18 * Bug #2685 - folder delete and annotations
19 * Bug #3381 - tools/rehash script is not 64bit safe
20 * Bug #3405 - Cyrus IMAP tls support for ctl_mboxlist
21 * Bug #3485 - cyr_expire tries to delete parent directories that are
22 not empty
23 * Bug #3582 - Extra LF+SP characters been inserted in the middle of
24 the XML attachments
25 * Bug #3598 - lmtp auditlog for murder proxy mode
26 * Bug #3623 - OpenBSD (and other platforms without working mmap)
27 multiple bugs
28 * Bug #3626 - Renaming a mailbox doesn't remove old folder
29 * Bug #3628 - folders with spaces and subfolders with same prefix as
30 parent folder don't show up
31 * Bug #3634 - RENAME INBOX no longer works
32 * Bug #3635 - cmd_rename() fails to check error codes
33 * Bug #3636 - unexpunge locks mailbox until all output is emitted
34 * Bug #3637 - imapd and ipop3d in 2.4 no longer log expunge events to
35 syslog
36 * Bug #3638 - sessionid logging improvements for murder environments
37 * Bug #3640 - LMTP accepts NULL bytes in headers, resulting in
38 incorrect header/mail size in meta-data
39 * Bug #3642 - iPhone 5 expects SPECIAL-USE in LIST output
40 * Bug #3649 - unable to remove mailbox
41 * Bug #3650 - ENVELOPE contains unexpected CRLF
42 * Bug #3645 - Ability to delete folder "shared"
43
044 Changes to the Cyrus IMAP Server since 2.4.12
145
246 * Bug #3565 - fix gcc compiler warnings - thanks Dilyan Palauzov
00 Upgrading From Previous Versions
1
2 Upgrading from 2.4.14
3
4 * We recommend that ALL sites with fulldirhash enabled run
5 tools/rehash on their mail spools after upgrading from 2.4.14.
6 There were serious 32 vs 64 bit hashing bugs which were made worse
7 with 2.4.14. NOTE: the syntax of tools/rehash has changed. Run it
8 without arguments to see a usage statement.
19
210 Upgrading from 2.4.12
311
30783078 }
30793079
30803080 /* local mailbox */
3081 if (!r) r = index_open(mailboxname, NULL, &state);
3081 if (!r) {
3082 struct index_init init;
3083 memset(&init, 0, sizeof(init));
3084 init.qresync = imapd_client_capa & CAPA_QRESYNC;
3085 init.userid = imapd_userid;
3086 init.authstate = imapd_authstate;
3087 init.out = imapd_out;
3088 r = index_open(mailboxname, &init, &state);
3089 }
30823090 if (!r) doclose = 1;
30833091
30843092 if (!r && !(state->myrights & ACL_READ))
31643172
31653173 if (!r) {
31663174 r = catenate_url(arg.s, cur_name, f, totalsize, parseerr);
3167 if (r) *url = arg.s;
3175 if (r) {
3176 *url = arg.s;
3177 return r;
3178 }
31683179 }
31693180 }
31703181 else {
26932693
26942694 r = mailbox_cacherecord(mailbox, &im->record);
26952695 if (r) return r;
2696
2696
26972697 /* Open the message file */
26982698 if (mailbox_map_message(mailbox, im->record.uid, &msg_base, &msg_size))
26992699 return IMAP_NO_MSGGONE;
27042704 if (size > msg_size) size = msg_size;
27052705
27062706 cacheitem = cacheitem_base(&im->record, CACHE_SECTION);
2707 cacheitem += CACHE_ITEM_SIZE_SKIP;
27082707
27092708 /* Special-case BODY[] */
27102709 if (!section || !*section) {
28012800 if (!data) {
28022801 /* failed to decode */
28032802 prot_printf(pout, " NIL)");
2803 r = 0;
28042804 goto done;
28052805 }
28062806 }
28362836
28372837 /* Complete extended URLFETCH response */
28382838 if (params & (URLFETCH_BODY | URLFETCH_BINARY)) prot_printf(pout, ")");
2839
2840 r = 0;
28392841
28402842 done:
28412843 /* Close the message file */
29682970 r = mailbox_rewrite_index_record(mailbox, &im->record);
29692971 if (r) return r;
29702972
2971 /* if it's silent and unchanged, update the seen value */
2972 if (storeargs->silent && im->told_modseq == oldmodseq)
2973 /* if it's silent and unchanged, update the seen value, but
2974 * not if qresync is enabled - RFC 4551 says that the MODSEQ
2975 * must always been told, and we prefer just to tell flags
2976 * as well in this case, it's simpler and not much more
2977 * bandwidth */
2978 if (!state->qresync && storeargs->silent && im->told_modseq == oldmodseq)
29732979 im->told_modseq = im->record.modseq;
29742980
29752981 return 0;
437437 sieve_reject_context_t *rc = (sieve_reject_context_t *) ac;
438438 script_data_t *sd = (script_data_t *) sc;
439439 message_data_t *md = ((deliver_data_t *) mc)->m;
440 char userbuf[MAX_MAILBOX_NAME];
441440 const char **body;
442441 const char *origreceip;
443442 int res;
457456 return SIEVE_OK;
458457 }
459458
460 strlcpy(userbuf, sd->username, sizeof(userbuf));
461 /* append default domain if no domain given */
462 if (config_defdomain && !strchr(userbuf, '@')) {
463 strlcat(userbuf, "@", sizeof(userbuf));
464 strlcat(userbuf, config_defdomain, sizeof(userbuf));
465 }
466
467459 body = msg_getheader(md, "original-recipient");
468460 origreceip = body ? body[0] : NULL;
469461 if ((res = send_rejection(md->id, md->return_path,
470 origreceip, userbuf,
462 origreceip, sd->username,
471463 rc->msg, md->data)) == 0) {
472464 snmp_increment(SIEVE_REJECT, 1);
473465 syslog(LOG_INFO, "sieve rejected: %s to: %s",
907899 sieve_execute_t *bc = NULL;
908900 script_data_t sdata;
909901 char userbuf[MAX_MAILBOX_BUFFER] = "";
902 char authuserbuf[MAX_MAILBOX_BUFFER];
910903 int r = 0;
911904 duplicate_key_t dkey = DUPLICATE_INITIALIZER;
912905
932925 }
933926
934927 if (user) strlcpy(userbuf, user, sizeof(userbuf));
935 mboxname_hiersep_toexternal(msgdata->namespace, userbuf, 0);
936928 if (domain) {
937929 strlcat(userbuf, "@", sizeof(userbuf));
938930 strlcat(userbuf, domain, sizeof(userbuf));
941933 sdata.mailboxname = mailbox;
942934
943935 if (user) {
944 sdata.authstate = auth_newstate(userbuf);
936 strlcpy(authuserbuf, userbuf, sizeof(authuserbuf));
937 if (config_getswitch(IMAPOPT_UNIXHIERARCHYSEP)) {
938 mboxname_hiersep_toexternal(msgdata->namespace, authuserbuf,
939 domain ? strcspn(authuserbuf, "@") : 0);
940 }
941 sdata.authstate = auth_newstate(authuserbuf);
945942 }
946943 else {
947944 sdata.authstate = msgdata->authstate;
948 }
945 }
949946
950947 r = sieve_execute_bytecode(bc, interp,
951948 (void *) &sdata, (void *) msgdata);
953950 if ((r == SIEVE_OK) && (msgdata->m->id)) {
954951 /* ok, we've run the script */
955952 char *sdb;
956
953
957954 /* slap the mailbox back on so we hash the envelope & id
958955 when we figure out whether or not to keep the message */
959956 snprintf(namebuf, sizeof(namebuf), "%s+%s@%s",
960957 user ? user : "", mailbox ? mailbox : "",
961958 domain ? domain : "");
962959 sdb = make_sieve_db(namebuf);
963
960
964961 dkey.id = msgdata->m->id;
965962 dkey.to = sdb;
966963 dkey.date = msgdata->m->date;
967964 duplicate_mark(&dkey, time(NULL), 0);
968965 }
969
966
970967 /* free everything */
971968 if (user && sdata.authstate) auth_freestate(sdata.authstate);
972969 sieve_script_unload(&bc);
973
970
974971 /* if there was an error, r is non-zero and
975972 we'll do normal delivery */
976973 return r;
10001000 const char *root = NULL;
10011001 char *newpartition = NULL;
10021002 char *mboxent = NULL;
1003 char *p;
10041003 mupdate_handle *mupdate_h = NULL;
10051004
10061005 /* 1. open mailbox */
927927 if (strlen(name) > MAX_MAILBOX_NAME)
928928 return IMAP_MAILBOX_BADNAME;
929929
930 /* because directory hashing could create ambiguous naming for
931 * a folder if the first item is a single character long, reject
932 * single character top level names */
933 if (name[1] == '.' || name[1] == '\0')
934 return IMAP_MAILBOX_BADNAME;
935
930936 for (i = 0; i < NUM_BADMBOXPATTERNS; i++) {
931937 g = glob_init(badmboxpatterns[i], GLOB_ICASE);
932938 if (GLOB_TEST(g, name) != -1) {
20922092
20932093 prot_printf(nntp_out, "281 User logged in\r\n");
20942094
2095 /* nntp_authstate may have been set as a side effect
2096 * of sasl_checkpass() calling mysasl_proxy_policy */
2097 if (nntp_authstate)
2098 auth_freestate(nntp_authstate);
2099
20952100 nntp_authstate = auth_newstate(nntp_userid);
20962101
20972102 /* Close IP-based telemetry log and create new log based on userid */
15021502 }
15031503 }
15041504
1505 /* popd_authstate may have been set as a side effect
1506 * of sasl_checkpass() calling mysasl_proxy_policy */
1507 if (popd_authstate)
1508 auth_freestate(popd_authstate);
1509
15051510 popd_authstate = auth_newstate(popd_userid);
15061511
15071512 openinbox();
122122 struct quotaentry *quota;
123123 int quota_num = 0, quota_alloc = 0;
124124
125 int firstquota = 0;
126125 int redofix = 0;
127126
128127 int main(int argc,char **argv)
298297
299298 *thisquota = -1;
300299
301 for (i = firstquota; i < quota_num; i++) {
300 for (i = 0; i < quota_num; i++) {
302301 const char *root = quota[i].quota.root;
303302
304303 /* have we already passed the name, then there can
305304 * be no further matches */
306305 if (compar(root, name) > 0)
307 return 0;
306 break;
308307
309308 /* is the mailbox within this root? */
310309 if (mboxname_is_prefix(name, root)) {
311310 /* fantastic, but don't return yet, we may find
312311 * a more exact match */
313 quota[i].refcount++;
314312 *thisquota = i;
315313 }
316 else {
317 /* not a match, so we can finish everything up to here */
318 while (firstquota < i) {
319 int r = fixquota_finish(firstquota);
320 if (r) return r;
321 firstquota++;
322 }
323 }
324 }
314 }
315
316 if (*thisquota >= 0)
317 quota[*thisquota].refcount++;
325318
326319 return 0;
327320 }
451444 int i, r;
452445 char buf[MAX_MAILBOX_BUFFER], *tail;
453446 size_t domainlen = 0;
447 int firstquota = 0;
454448
455449 buf[0] = '\0';
456450 tail = buf;
439439 /* If enabled, a special comparator will be used which will correctly
440440 sort mailbox names that contain characters such as ' ' and '-'.
441441 .PP
442 Note that this option SHOULD NOT be changed on a live system.
443 The mailboxes database should be dumped before the option is changed,
444 removed, and then undumped after changing the option. */
442 Note that this option SHOULD NOT be changed on a live system. The
443 mailboxes database should be dumped (ctl_mboxlist) before the
444 option is changed, removed, and then undumped after changing the
445 option. When not using flat files for the subscriptions databases
446 the same has to be done (cyr_dbtool) for each subscription database
447 See improved_mboxlist_sort.html.*/
445448
446449 { "internaldate_heuristic", "standard", ENUM("standard", "receivedheader") }
447450 /* Mechanism to determine email internaldates on delivery/reconstruct.
268268
269269 if (full) {
270270 unsigned char *pt;
271 unsigned long long int n;
271 unsigned int n;
272272 enum {
273273 DIR_X = 3,
274274 DIR_Y = 5,
280280 pt = (unsigned char *)name;
281281 while (*pt && *pt != '.') {
282282 n = ((n << DIR_X) ^ (n >> DIR_Y)) ^ *pt;
283 n &= UINT32_MAX;
283284 ++pt;
284285 }
285286 c = DIR_A + (n % DIR_P);
384384 If enabled, a special comparator will be used which will correctly
385385 sort mailbox names that contain characters such as ' ' and '-'.
386386 .PP
387 Note that this option SHOULD NOT be changed on a live system.
388 The mailboxes database should be dumped before the option is changed,
389 removed, and then undumped after changing the option.
387 Note that this option SHOULD NOT be changed on a live system. The
388 mailboxes database should be dumped (ctl_mboxlist) before the
389 option is changed, removed, and then undumped after changing the
390 option. When not using flat files for the subscriptions databases
391 the same has to be done (cyr_dbtool) for each subscription database
392 See improved_mboxlist_sort.html.
390393 .IP "\fBinternaldate_heuristic:\fR standard" 5
391394 Mechanism to determine email internaldates on delivery/reconstruct.
392395 "standard" uses time() when delivering a message, mtime on reconstruct.
123123 .\" ========================================================================
124124 .\"
125125 .IX Title "SIEVESHELL 1"
126 .TH SIEVESHELL 1 "2012-03-12" "perl v5.14.2" "User Contributed Perl Documentation"
126 .TH SIEVESHELL 1 "2012-04-18" "perl v5.14.2" "User Contributed Perl Documentation"
127127 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
128128 .\" way too many mistakes in technical documents.
129129 .if n .ad l
0 #!/bin/sh
1 #
2 # Copyright (c) 1994-2008 Carnegie Mellon University. All rights reserved.
0 #!/usr/bin/env perl
1 #
2 # Copyright (c) 1994-2012 Carnegie Mellon University. All rights reserved.
33 #
44 # Redistribution and use in source and binary forms, with or without
55 # modification, are permitted provided that the following conditions
3737 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
3838 # AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
3939 # OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40 #
41 # $Id: rehash,v 1.11 2010/01/06 17:02:01 murch Exp $
42
43 exec perl -x -S $0 ${1+"$@"} # -*-perl-*-
44 #!perl -w
45 # script to upgrade from simple hashing scheme to full hashing scheme
46 # make sure you run it as the cyrus user
47 #
48 # Written by Gary Mills <mills@cc.UManitoba.CA>
49
50 if ($] !~ /^5\..*/) {
51 # uh-oh. this isn't perl 5.
52 foreach (split(/:/, $ENV{PATH})) { # try to find "perl5".
53 exec("$_/perl5", "-x", "-S", $0, @ARGV) if (-x "$_/perl5");
54 }
55 # we failed. bail.
56 die "Your perl is too old; I need perl 5.\n";
57 }
58
59 # load the real script. this is isolated in an 'eval' so perl4 won't
60 # choke on the perl5-isms.
61 eval join("\n", <DATA>);
62 if ($@) { die "$@"; }
63
64 __END__
65 require 5;
66 require Math::BigInt;
67
40
41 use strict;
42 use warnings;
43
44 use Getopt::Std;
45
46 my %Opts;
47 getopts('vnhfFiI', \%Opts);
48 usage() if $Opts{h};
49
50 my $OPT_NoAction = $Opts{n};
51 my $OPT_Verbose = $Opts{v} || $Opts{n};
52
53 # non-buffered output
6854 $| = 1;
6955
56 # XXX - actually read the cyrus username from the imapd.conf and
57 # change ownership as appropriate?
7058 die "must not run as root" if ($< == 0);
7159
72 if ("-i" eq $ARGV[0]) {
73 $interactive = 1;
74 shift @ARGV;
75 }
76 if ("-f" eq $ARGV[0]) {
77 $force = 1;
78 shift @ARGV;
79 }
80 if ("-h" eq $ARGV[0] || @ARGV < 1) {
81 print "usage: rehash [-i] [-f] none|basic|full [imapd.conf]\n";
82 print " -i interactive\n";
83 print " -f keep going on errors\n";
84 exit;
85 }
86
87 $MOVE_DOMAIN_CONF = 1;
88 $MOVE_DOMAIN_SIEVE = 2;
89 $MOVE_DOMAIN_PART = 3;
90
91 $tonone = 1 if ("none" eq $ARGV[0]);
92 $tobasic = 1 if ("basic" eq $ARGV[0]);
93 $tofull = 1 if ("full" eq $ARGV[0]);
94 unless ($tonone || $tobasic || $tofull) {
95 print "rehash: one of none/basic/full required\n";
96 exit;
97 }
98 shift @ARGV;
60 my $imapdconf = shift || usage();
9961
10062 my @bdirs = ("a".."z");
10163 my @fdirs = ("A".."W");
102 my $dirs = [@bdirs,@fdirs] if $tonone;
103
104 if ($tobasic) {
105 $dirs = \@bdirs;
106 $old = \@fdirs;
107 }
108
109 if ($tofull) {
110 $dirs = \@fdirs;
111 $old = \@bdirs;
112 }
113
114 sub ouch {
115 my $msg = shift;
116
117 if ($force) {
118 print "fatal error: $msg\n";
119 } else {
120 print "error: $msg\n";
121 exit 1;
122 }
123 }
124
125 sub dir_hash_c_32 {
64 my %ishash = map { $_ => 1 } (@bdirs, @fdirs);
65
66 # evil globals
67 my @configs = ($imapdconf);
68 my $confdir = "/var/imap";
69 my @parts;
70 my $yn = "y";
71 my $sievedir = "/usr/sieve";
72 my $nosievedir = 0;
73 my $hashimapspool = 0;
74 my $fulldirhash = 0;
75 my $virtdomains = 0;
76
77 while (my $conf = shift @configs) {
78 read_conf($conf);
79 }
80
81 $fulldirhash = 0 if $Opts{f};
82 $fulldirhash = 1 if $Opts{F};
83 $hashimapspool = 0 if $Opts{i};
84 $hashimapspool = 1 if $Opts{I};
85
86 print "converting configuration directory $confdir... ";
87
88 foreach my $i ("user", "proc", "lock", "db", "socket", "log", "msg", "quota") {
89 ensure_dir("$confdir/$i");
90 }
91
92 # *** rehash the domain subdirectory to the new format,
93 # don't worry about internal format yet
94 if ($virtdomains) {
95 print "domain ";
96 ensure_dir("$confdir/domain");
97 move_domains("$confdir/domain", 'conf');
98 }
99
100 # *** user subdirectory; holds subscription files
101 print "user ";
102 move_users("$confdir/user");
103
104 # *** quota subdirectory; holds quota files for each quotaroot
105 print "quota ";
106 move_quotas("$confdir/quota");
107
108 print "done\n";
109
110 # create the sieve stuff
111 unless ($nosievedir) {
112 print "sieve $sievedir... ";
113
114 ensure_dir($sievedir);
115 move_sieve($sievedir);
116
117 print "done\n";
118 }
119
120 # *** now for each data partition
121 while (my $part = shift @parts) {
122 print "partition $part... ";
123
124 ensure_dir($part);
125 # stage is good too
126 ensure_dir("$part/stage.");
127
128 move_part($part);
129
130 print "done\n";
131 }
132
133 sub usage {
134 die <<EOF
135 usage: $0 [-v] [-n] imapd.conf
136
137 -v verbose
138 -n no change - just show what would be done
139 -f force fulldirhash: no
140 -F force fulldirhash: yes
141 -i force hashimapspool: no
142 -I force hashimapspool: yes
143
144 NOTE: imapd.conf must always be provided. On a normal system
145 this will be /etc/imapd.conf. The correct hashing settings will
146 be read from the provided imapd.conf, or can be overridden with
147 options.
148
149 In verbose mode, each rename command will be printed, as well as
150 any creation or deletion of folders.
151
152 In "no change" mode, it will just print the changes. Note,
153 verbose is always turned on in no-change mode.
154
155 NOTE 2: It should be safe to run fixhash on a running system, but
156 it may mess things up horribly if you have some processes still
157 running with old config, and some with new - so it is always
158 recommended to fully shut down Cyrus, change the configuration
159 file, run fixhash, and then start Cyrus again.
160 EOF
161 }
162
163 # force 32 bit hashing only
164 sub dir_hash_c {
126165 my $name = shift;
127 my $uint32 = (2**32);
166 my $isspool = shift;
167
128168 my ($h, $n);
129169
130 if ($tofull) {
170 if ($fulldirhash) {
171 $name =~ s/\..*//; # remove trailing dots
131172 $n = 0;
132173 foreach my $b (split(/ */, $name)) {
133 $n = ((($n << 3) ^ ($n >> 5)) % $uint32) ^ ord($b);
174 $n = (($n << 3) ^ ($n >> 5)) ^ ord($b);
175 $n &= 4294967295; # UINT32_MAX
134176 }
135177 $h = chr(ord('A') + ($n % 23));
136178 return $h;
137179 }
138 elsif ($tobasic) {
180 else {
139181 $h = lc(substr($name, 0, 1));
140182 if (!($h =~ /[a-z]/)) { $h = 'q'; }
141183 return $h;
142184 }
143185 }
144186
145 sub dir_hash_c_64 {
146 my $name = shift;
147 my ($h, $n);
148
149 if ($tofull) {
150 $n = Math::BigInt->new(0);
151 foreach my $b (split(/ */, $name)) {
152 $n = (($n << 3) ^ ($n >> 5)) ^ ord($b);
153 }
154 $h = chr(ord('A') + ($n % 23));
155 return $h;
156 }
157 elsif ($tobasic) {
158 $h = lc(substr($name, 0, 1));
159 if (!($h =~ /[a-z]/)) { $h = 'q'; }
160 return $h;
161 }
187 sub hash_path {
188 my $path = shift;
189 my $item = shift;
190 my $isspool = shift;
191 my $skiptochar = shift;
192
193 return "$path/$item" unless ($hashimapspool or not $isspool);
194
195 my $tohash = $item;
196 if ($skiptochar) {
197 # strip up to and including the character
198 $tohash =~ s/^.*?\Q$skiptochar//;
199 if ($skiptochar eq '/' and $tohash =~ m/\./) {
200 # we've got a top level directory, oops
201 $tohash = $item;
202 $tohash =~ s{/.*$}{};
203 }
204 }
205
206 return "$path/" . dir_hash_c($tohash) . "/$item";
162207 }
163208
164209 sub read_conf {
182227 push @parts, $1;
183228 }
184229 if (/^hashimapspool:\s*(1|t|yes|on)/) {
185 $hashispool = 1;
230 $hashimapspool = 1;
186231 print "i will also hash partitions.\n";
232 }
233 if (/^fulldirhash/) {
234 $fulldirhash = 1;
187235 }
188236 if (/^sieveusehomedir:\s+(1|t|yes|on)/) {
189237 $nosievedir = 1;
193241 $sievedir = $1;
194242 print "you are using $sievedir as your sieve directory.\n";
195243 }
196 if (/^virtdomains:\s+(1|t|yes|on)/) {
244 if (/^virtdomains:\s+(1|t|yes|on|userid)/) {
197245 $virtdomains = 1;
198246 print "i will deal with virtual domains.\n";
199247 }
201249 close CONF;
202250 }
203251
204 $imapdconf = shift || "/etc/imapd.conf";
205
206 $yn = "y";
207 $sievedir = "/usr/sieve";
208 $nosievedir = 0;
209 $hashispool = 0;
210 $virtdomains = 0;
211
212 push @configs, $imapdconf;
213
214 while ($conf = shift @configs) {
215 read_conf($conf);
216 }
217
218 if (! $confdir) { $confdir = "/var/imap"; }
219
220 if ($interactive) {
221 print "upgrade $confdir? ";
222 $yn = <STDIN>;
223 }
224 if ($yn =~ /^y/) {
225 unless (-d $confdir) { print "creating $confdir...\n";
226 mkdir $confdir, 0755;
227 }
228 print "converting configuration directory $confdir...";
229 chdir $confdir or die "couldn't change to $confdir";
230
231 foreach $i ("user", "proc", "lock", "db", "socket", "log", "msg", "quota") {
232 unless (-d $i) {
233 print "creating $i...\n";
234 mkdir $i, 0755;
235 }
236 }
237
238 # *** rehash the domain subdirectory to the new format,
239 # don't worry about internal format yet
240 if($virtdomains) {
241 print "domain ";
242 chdir "domain" or die "couldn't change to domain subdir";
243 &move_domains($MOVE_DOMAIN_CONF);
244 chdir "..";
245 }
246
247 # *** user subdirectory; holds subscription files
248 print "user ";
249 chdir "user" or die "couldn't change to user subdir";
250 &move_users;
251 chdir "..";
252
253 # *** quota subdirectory; holds quota files for each quotaroot
254 print "quota ";
255 chdir "quota" or die "couldn't change to quota subdir";
256 &move_quotas;
257 print "done\n";
258 }
259
260 # create the sieve stuff
261 unless ($nosievedir) {
262 print "converting $sievedir...\n";
263
264 mkdir $sievedir, 0755;
265 if (chdir $sievedir) {
266 &move_sieve;
267 }
268 }
269
270 # *** now for each data partition
271 my $i;
272 my $f;
273
274 while ($part = shift @parts) {
275 if ($interactive) {
276 print "upgrade $part? ";
277 $yn = <STDIN>;
278 }
279 if ($yn =~ /^y/) {
280 unless (-d $part) {
281 print "creating $part...\n";
282 mkdir $part, 0755;
283 }
284 print "converting data partition $part...";
285 chdir $part or die "couldn't chdir to $part";
286
287 if ($hashispool) {
288 &move_part;
289
290 chdir $part or die "couldn't chdir to $part";
291 mkdir "stage.", 0755;
292 }
293
294 print "done\n";
295 }
296 }
297
298 sub do_subdomain_conf {
299 if(-d "quota") {
300 chdir "quota";
301 &move_quotas;
302 chdir "..";
303 }
304 if(-d "user") {
305 chdir "user";
306 &move_users;
307 chdir "..";
308 }
309 }
310
311 sub move_domains {
312 my $type_of_move = shift;
313
314 if(!defined($type_of_move) || !$type_of_move) {
315 die "move_domains called badly";
316 }
317
318 my $i;
319 my $s;
320 my $h_32;
321 my $h_64;
322 my $mbox;
323
324 foreach $i (@{$dirs}) {
325 if ($tonone) {
326 if (opendir SUB, $i) {
327 while ($s = readdir SUB) {
328 if ($s =~ /^\./s) { next; }
329 chdir "$i/$s";
330 &do_subdomain;
331 chdir "../..";
332 rename ("$i/$s", "$s") or die "couldn't move $s back!";
333 }
334 closedir SUB;
335 rmdir "$i" or die "couldn't remove $i";
336 }
252 sub add_found {
253 # here be dragons, eep
254 my $type = shift;
255 my $found = shift;
256 my $name = shift;
257 my $location = shift;
258
259 if ($type ne 'part') {
260 if ($found->{$name}) {
261 die "FOUND BOTH $found->{$name} and $location - you need to fix this by hand\n";
262 }
263 $found->{$name} = $location;
264 return;
265 }
266
267 unless (opendir(SUB, $location)) {
268 print "Failed to open directory $location\n";
269 die unless $OPT_NoAction;
270 return;
271 }
272 while (my $sub = readdir SUB) {
273 next if $sub =~ m/^\./;
274 my $key = "$name/$sub";
275 if ($found->{$key}) {
276 die "FOUND BOTH $found->{$key} and $location/$sub - you need to fix this by hand\n";
277 }
278 $found->{$key} = "$location/$sub";
279 }
280 closedir(SUB);
281 }
282
283 sub find_items {
284 my $path = shift;
285 my $type = shift;
286 my %found;
287 my @subs;
288
289 unless (opendir(ITEMS, $path)) {
290 print "Failed to open directory $path\n";
291 die unless $OPT_NoAction;
292 return;
293 }
294 while (my $item = readdir ITEMS) {
295 # guaranteed evil
296 next if $item =~ m/^\./;
297 next if $item eq 'lost+found';
298 next if $item eq 'stage.';
299 next if $item eq 'sync.';
300 next if $item eq 'domain'; # this is just stupid, it should at LEAST have a dot
301
302 if ($ishash{$item}) {
303 push @subs, $item;
337304 }
338305 else {
339 unless (-d $i) {
340 mkdir ("$i", 0755) or ouch "couldn't create $i";
341 }
342 }
343 }
344 unless ($tonone) {
345 foreach $i (@{$old}) {
346 if (opendir SUB, $i) {
347 while ($s = readdir SUB) {
348 if ($s =~ /^\./s) { next; }
349
350 chdir "$i/$s";
351
352 if($type_of_move == $MOVE_DOMAIN_CONF) {
353 &do_subdomain_conf;
354 } elsif ($type_of_move == $MOVE_DOMAIN_SIEVE) {
355 &move_sieve;
356 } elsif ($type_of_move == $MOVE_DOMAIN_PART) {
357 &move_part;
358 } else {
359 die "bad domain move mode: $type_of_move";
360 }
361
362 chdir "../..";
363
364 $h_32 = dir_hash_c_32($s);
365 $h_64 = dir_hash_c_64($s);
366 print "moving $i/$s to $h_64/$s\n";
367 if ("$h_32" eq "$h_64") {
368 rename ("$i/$s", "$h_64/$s") or ouch "couldn't move $s back!";
369 } else {
370 rename ("$i/$s", "$h_32/$s") or ouch "couldn't move $s back!";
371 rename ("$h_32/$s", "$h_64/$s") or ouch "couldn't move $s back!";
372 }
373 }
374 closedir SUB;
375 rmdir "$i" or die "couldn't remove $i";
376 }
377 }
378 opendir (USER, ".");
379 while ($f = readdir USER) {
380 if ($f =~ /^\./s) { next; }
381
382 # don't move the hashed directories themselves
383 my $flag = 0;
384 foreach $item (@{$dirs}) {
385 if($item eq $f) {
386 $flag = 1;
387 $break;
388 }
389 }
390 next if($flag);
391
392 # hash on name before '.sub' suffix
393 print "$f\n";
394 $h_32 = dir_hash_c_32($f);
395 $h_64 = dir_hash_c_64($f);
396 if ("$h_32" eq "$h_64") {
397 rename ($f, "$h_64/$f") or ouch "couldn't move $f into $h_64";
398 } else {
399 rename ($f, "$h_32/$f") or ouch "couldn't move $f into $h_32";
400 rename ("$h_32/$f", "$h_64/$f") or ouch "couldn't move $h_32 into $h_64";
401 }
402 }
403 closedir USER;
404 }
405 }
406
407 sub move_users {
408 my $i;
409 my $s;
410 my $h_32;
411 my $h_64;
412 my $f;
413 my $mbox;
414
415 foreach $i (@{$dirs}) {
416 if ($tonone) {
417 if (opendir SUB, $i) {
418 while ($s = readdir SUB) {
419 if ($s =~ /^\./s) { next; }
420 rename ("$i/$s", "$s") or die "couldn't move $s back!";
421 }
422 closedir SUB;
423 rmdir "$i" or die "couldn't remove $i";
424 }
425 } else {
426 unless (-d $i) {
427 mkdir ("$i", 0755) or ouch "couldn't create $i";
428 }
429 }
430 }
431 unless ($tonone) {
432 foreach $i (@{$old}) {
433 if (opendir SUB, $i) {
434 while ($s = readdir SUB) {
435 if ($s =~ /^\./s) { next; }
436 # hash on name before '.sub' suffix
437 if ($s =~ /^(.+)\./) {
438 $h_32 = dir_hash_c_32($1);
439 $h_64 = dir_hash_c_64($1);
440 if ("$h_32" eq "$h_64") {
441 rename ("$i/$s", "$h_64/$s") or ouch "couldn't move $s back!";
442 } else {
443 rename ("$i/$s", "$h_32/$s") or ouch "couldn't move $s back!";
444 rename ("$h_32/$s", "$h_64/$s") or ouch "couldn't move $s back!";
445 }
446 }
447 }
448 closedir SUB;
449 rmdir "$i" or die "couldn't remove $i";
450 }
451 }
452 opendir (USER, ".");
453 while ($f = readdir USER) {
454 if ($f =~ /^\./s) { next; }
455 # hash on name before '.sub' suffix
456 if ($f =~ /^(.+)\./) {
457 print "$f\n";
458 $h_32 = dir_hash_c_32($1);
459 $h_64 = dir_hash_c_64($1);
460 if ("$h_32" eq "$h_64") {
461 rename ($f, "$h_64/$f") or ouch "couldn't move $f into $h_64";
462 } else {
463 rename ($f, "$h_32/$f") or ouch "couldn't move $f into $h_32";
464 rename ("$h_32/$f", "$h_64/$f") or ouch "couldn't move $h_32/$f into $h_64";
465 }
466 }
467 }
468 closedir USER;
469 }
470 }
471
472 sub move_quotas {
473 my $i;
474 my $s;
475 my $h_32;
476 my $h_64;
477 my $mbox;
478
479 # first, create directories we know can't conflict with existing files
480 foreach $i (@{$dirs}) {
481 if ($tonone) {
482 if (-d $i) {
483 rename ($i, ".$i") or die "couldn't rename $i to .$i";
484 opendir SUB, ".$i";
485 while ($s = readdir SUB) {
486 if ($s =~ /^\./s) { next; }
487 rename(".$i/$s", $s) or die "couldn't move $s back!";
488 }
489 closedir SUB;
490 rmdir ".$i" or die "couldn't remove .$i";
491 }
492 }
493 else {
494 if (-d $i) {
495 rename ($i, ".$i") or die "couldn't rename $i to .$i";
496 }
497 else {
498 mkdir (".$i", 0755);
499 }
500 }
501 }
502
503 # now for each file, move it into the appropriate directory
504 unless ($tonone) {
505 foreach $i (@{$old}) {
506 if (opendir SUB, $i) {
507 while ($s = readdir SUB) {
508 # hash on name after 'user.'
509 if ($s =~ /^.+\.(.+)$/) {
510 $h_32 = dir_hash_c_32($1);
511 $h_64 = dir_hash_c_64($1);
512 if ("$h_32" eq "$h_64") {
513 rename ("$i/$s", ".$h_64/$s")
514 or ouch "couldn't move $s back!";
515 } else {
516 rename ("$i/$s", ".$h_32/$s")
517 or ouch "couldn't move $s back!";
518 rename (".$h_32/$s", ".$h_64/$s")
519 or ouch "couldn't move $s back!";
520 }
521 }
522 }
523 closedir SUB;
524 rmdir "$i" or die "couldn't remove $i";
525 }
526 }
527 opendir QUOTA, ".";
528 while ($mbox = readdir QUOTA) {
529 if ($mbox =~ /^\./s) { next; }
530
531 # hash on name after 'user.'
532 if ($mbox =~ /^.*\.(.*)$/) {
533 $h_32 = dir_hash_c_32($1);
534 $h_64 = dir_hash_c_64($1);
535 if ("$h_32" eq "$h_64") {
536 rename ($mbox, ".$h_64/$mbox")
537 or ouch "couldn't move $mbox into $h_64";
538 } else {
539 rename ($mbox, ".$h_32/$mbox")
540 or ouch "couldn't move $mbox into $h_32";
541 rename (".$h_32/$mbox", ".$h_64/$mbox")
542 or ouch "couldn't move $mbox into $h_64";
543 }
306 add_found($type, \%found, $item, "$path/$item");
307 }
308 }
309 closedir(ITEMS);
310
311 foreach my $sub (@subs) {
312 next unless opendir(ITEMS, "$path/$sub");
313 while (my $item = readdir ITEMS) {
314 next if $item =~ m/^\./;
315 # we can't fix duplicate directories ourselves!
316 add_found($type, \%found, $item, "$path/$sub/$item");
317 }
318 closedir(ITEMS);
319 }
320
321 return %found;
322 }
323
324 sub do_moves {
325 my $path = shift;
326 my $isspool = shift;
327 my $skiptochar = shift;
328 my %found = @_;
329
330 foreach my $item (sort keys %found) {
331 my $src = $found{$item};
332 my $dst = hash_path($path, $item, $isspool, $skiptochar);
333
334 if ($src ne $dst) {
335 ensure_parent($dst);
336 print "rename $src to $dst: " if $OPT_Verbose;
337 if ($OPT_NoAction) {
338 print "skipped\n" if $OPT_Verbose;
544339 next;
545340 }
546
547 # we should try to hash the entire file
548 $h_32 = dir_hash_c_32($mbox);
549 $h_64 = dir_hash_c_64($mbox);
550 if ("$h_32" eq "$h_64") {
551 rename ($mbox, ".$h_64/$mbox")
552 or ouch "couldn't move $mbox into $h_64";
553 } else {
554 rename ($mbox, ".$h_32/$mbox")
555 or ouch "couldn't move $mbox into $h_32";
556 rename (".$h_32/$mbox", ".$h_64/$mbox")
557 or ouch "couldn't move $mbox into $h_64";
341 rename($src, $dst) or die "failed to rename $src to $dst";
342 print "done\n" if $OPT_Verbose;
343 }
344 }
345 }
346
347 sub move_domains {
348 my $path = shift;
349 my $type_of_move = shift || die "move_domains called badly";
350 my $isspool = ($type_of_move eq 'part');
351
352 my %found = find_items($path, 'domain');
353
354 # let's do the subdirs first, then move the top levels
355 foreach my $item (sort keys %found) {
356 if ($type_of_move eq 'conf') {
357 if (-d "$path/quota") {
358 move_quotas("$path/quota");
558359 }
559 next;
560
561 }
562 closedir QUOTA;
563
564 # now move each temporary directory to the right place
565 foreach $i (@{$dirs}) {
566 rename (".$i", $i) or ouch "couldn't rename $i into place";
567 }
568 }
569 }
570
571 sub move_sieve {
572 my $i;
573 my $s;
574 my $h_32;
575 my $h_64;
576 my $mbox;
577
578 foreach $i (@{$dirs}) {
579 unless ($tonone) {
580 if (-d $i) {
581 rename ($i, ".$i") or die "couldn't rename $i to .$i";
582 }
583 else {
584 mkdir (".$i", 0755);
585 }
360 if (-d "$path/user") {
361 move_users("$path/user");
586362 }
587 else {
588 rmdir "$i";
363 } elsif ($type_of_move eq 'sieve') {
364 move_sieve($found{$item}, 1);
365 } elsif ($type_of_move == 'part') {
366 move_part($found{$item}, 1);
367 } else {
368 die "bad domain move mode: $type_of_move";
369 }
370 }
371
372 do_moves($path, $isspool, undef, %found);
373 tidy_up($path, $isspool, 0);
374 }
375
376 sub move_users {
377 my $path = shift;
378
379 my %found = find_items($path, 'user');
380 do_moves($path, 0, undef, %found);
381 tidy_up($path, 0, 0);
382 }
383
384 sub move_quotas {
385 my $path = shift;
386
387 my %found = find_items($path, 'quota');
388 do_moves($path, 0, '.', %found);
389 tidy_up($path, 0, 0);
390 }
391
392 sub move_sieve {
393 my $path = shift;
394 my $indomain = shift;
395
396 my %found = find_items($path, 'sieve');
397
398 if ($virtdomains and not $indomain) {
399 ensure_dir("$path/domain");
400 move_domains("$path/domain", 'sieve');
401 }
402
403 do_moves($path, 0, undef, %found);
404 tidy_up($path, 0, 0);
405 }
406
407 # could be data or meta
408 sub move_part {
409 my $path = shift;
410 my $indomain = shift;
411
412 # let's just assume nobody is being stupid and creating 1 character toplevel names
413 my %found = find_items($path, 'part');
414
415 if ($virtdomains and not $indomain) {
416 ensure_dir("$path/domain");
417 move_domains("$path/domain", 'part');
418 }
419
420 do_moves($path, 1, '/', %found);
421 tidy_up($path, 1, 1);
422 }
423
424 sub ensure_dir {
425 my $dir = shift;
426 unless (-d $dir) {
427 ensure_parent($dir);
428 print "mkdir $dir: " if $OPT_Verbose;
429 if ($OPT_NoAction) {
430 print "skipped\n" if $OPT_Verbose;
431 return;
432 }
433 mkdir($dir, 0755) || die "Failed to create $dir: $!";
434 print "done\n" if $OPT_Verbose;
435 }
436 return 1;
437 }
438
439 sub ensure_parent {
440 my $path = shift;
441 $path =~ s{/[^/]+$}{};
442 return ensure_dir($path);
443 }
444
445 sub remove_dir {
446 my $dir = shift;
447 return 1 unless -d $dir;
448 print "rmdir $dir: " if $OPT_Verbose;
449 if ($OPT_NoAction) {
450 print "skipped\n" if $OPT_Verbose;
451 return;
452 }
453 if (opendir(DH, $dir)) {
454 my @extra;
455 while (my $item = readdir(DH)) {
456 next if $item eq '.';
457 next if $item eq '..';
458 push @extra, $item;
459 }
460 closedir(DH);
461 if (@extra) {
462 my $num = @extra;
463 my $s = $num == 1 ? '' : 's';
464 print "skipped, $num extra item$s found, including $dir/$extra[0]\n";
465 return;
466 }
467 }
468 rmdir($dir) || die "Failed to remove $dir: $!";
469 print "done\n" if $OPT_Verbose;
470 return 1;
471 }
472
473 sub tidydir {
474 my $dir = shift;
475 my $onemore = shift;
476
477 if ($onemore) {
478 if (opendir(DIR, $dir)) {
479 while (my $item = readdir DIR) {
480 next if $item =~ m/^\./;
481 remove_dir("$dir/$item");
589482 }
590 }
591 unless ($tonone) {
592 foreach $i (@{$old}) {
593 if (opendir SUB, $i) {
594 while ($s = readdir SUB) {
595 unless ($s =~ /^\./) {
596 $h_32 = dir_hash_c_32($s);
597 $h_64 = dir_hash_c_64($s);
598 if ("$h_32" eq "$h_64") {
599 rename ("$i/$s", ".$h_64/$s")
600 or ouch "couldn't move $s back!";
601 } else {
602 rename ("$i/$s", ".$h_32/$s")
603 or ouch "couldn't move $s back!";
604 rename (".$h_32/$s", ".$h_64/$s")
605 or ouch "couldn't move $s back!";
606 }
607 }
608 }
609 closedir SUB;
610 rmdir "$i" or die "couldn't remove $i";
611 }
612 }
613 # now move each temporary directory to the right place
614 foreach $i (@{$dirs}) {
615 rename (".$i", $i) or ouch "couldn't rename $i into place";
616 }
617 }
618
619 if($virtdomains && chdir "domain") {
620 &move_domains($MOVE_DOMAIN_SIEVE);
621 chdir "..";
622 }
623 }
624
625 sub move_part {
626 my $i;
627 my $s;
628 my $t;
629 my $h_32;
630 my $h_64;
631 my $dir;
632 my $sub;
633 my $ismbox;
634
635 foreach $i (@{$dirs}) {
636 if ($tonone) {
637 if (-d $i) {
638 rename ($i, ".$i") or die "couldn't rename $i to .$i";
639 print "$i ";
640
641 opendir SUB, ".$i";
642 while ($s = readdir SUB) {
643 if ($s =~ /^\./s) { next; }
644 mkdir $s, 0755; # ignore errors as it might already exist
645
646 opendir MV, ".$i/$s";
647 while ($t = readdir MV) {
648 if ($t =~ /^\./s) { next; }
649 rename (".$i/$s/$t", "$s/$t")
650 or die "couldn't rename .$i/$s/$t to $s/$t";
651 }
652 closedir MV;
653 }
654 closedir SUB;
655 rmdir ".$i" or die "could not remove .$i";
656 }
657 print "done\n";
658 }
659 else {
660 mkdir (".$i", 0755) or ouch "couldn't create .$i";
661 }
662 }
663
664 unless ($tonone) {
665 foreach $i (@{$old}) {
666 if (opendir SUB, $i) {
667 while ($dir = readdir SUB) {
668 if ($dir =~ /^\./s) { next; }
669 # process $dir
670 print "$i/$dir ";
671 opendir DIR, "$i/$dir";
672 $ismbox = 0;
673 while ($sub = readdir DIR) {
674 if ($sub =~ /^\./s) { next; }
675 # if there's a dot in this, we're a mbox and
676 # this isn't a child
677 if ($sub =~ /(.*)\.(.*)/) { $ismbox = 1; next; }
678
679 print "/$sub ";
680 $h_32 = dir_hash_c_32($sub);
681 $h_64 = dir_hash_c_64($sub);
682 mkdir (".$h_64/$dir", 0755); # might already be there
683 if ("$h_32" eq "$h_64") {
684 rename ("$i/$dir/$sub", ".$h_64/$dir/$sub")
685 or ouch "couldn't move $dir/$sub into $h_64";
686 } else {
687 mkdir (".$h_32/$dir", 0755); # might already be there
688 rename ("$i/$dir/$sub", ".$h_32/$dir/$sub")
689 or ouch "couldn't move $dir/$sub into $h_32";
690 rename (".$h_32/$dir/$sub", ".$h_64/$dir/$sub")
691 or ouch "couldn't move $dir/$sub into $h_32";
692 rmdir ".$h_32/$dir";
693 }
694 }
695 closedir DIR;
696 # if $ismbox is set, then $dir is a mailbox of it's own right
697 if ($ismbox) {
698 $h_32 = dir_hash_c_32($dir);
699 $h_64 = dir_hash_c_64($dir);
700 mkdir (".$h_64/$dir", 0755); # might already be there
701 opendir DIR, "$i/$dir";
702 while ($sub = readdir DIR) {
703 if ($sub =~ /^\./s) { next; }
704 print "/$sub ";
705 if ("$h_32" eq "$h_64") {
706 rename ("$i/$dir/$sub", ".$h_64/$dir/$sub")
707 or ouch "couldn't move $dir into $h_64";
708 } else {
709 mkdir (".$h_32/$dir", 0755); # might already be there
710 rename ("$i/$dir/$sub", ".$h_32/$dir/$sub")
711 or ouch "couldn't move $dir into $h_32";
712 rename (".$h_32/$dir/$sub", ".$h_64/$dir/$sub")
713 or ouch "couldn't move $dir into $h_64";
714 rmdir ".$h_32/$dir";
715 }
716 }
717 closedir DIR;
718 }
719
720 rmdir "$i/$dir" or print "\ncouldn't remove '$dir'??\n";
721 }
722 closedir SUB;
723 rmdir "$i" or die "couldn't remove $i";
724 }
725 }
726 opendir PART, ".";
727 while ($dir = readdir PART) {
728 if ($dir =~ /^\./s) { next; }
729 if ($dir eq "lost+found") { next; }
730 if ($dir eq "stage.") { next; }
731 if ($dir eq "domain") {
732 if(chdir "domain") {
733 &move_domains($MOVE_DOMAIN_PART);
734 chdir "..";
735 }
736 next;
737 }
738
739 # process $dir
740 print "$dir ";
741 opendir DIR, $dir;
742 $ismbox = 0;
743 while ($sub = readdir DIR) {
744 if ($sub =~ /^\./s) { next; }
745 # if there's a dot in this, we're a mbox and
746 # this isn't a child
747 if ($sub =~ /(.*)\.(.*)/) { $ismbox = 1; next; }
748
749 $h_32 = dir_hash_c_32($sub);
750 $h_64 = dir_hash_c_64($sub);
751 mkdir (".$h_64/$dir", 0755); # might already be there
752 if ("$h_32" eq "$h_64") {
753 rename ("$dir/$sub", ".$h_64/$dir/$sub")
754 or ouch "couldn't move $dir/$sub into $h_64";
755 } else {
756 mkdir (".$h_32/$dir", 0755); # might already be there
757 rename ("$dir/$sub", ".$h_32/$dir/$sub")
758 or ouch "couldn't move $dir/$sub into $h_32";
759 rename (".$h_32/$dir/$sub", ".$h_64/$dir/$sub")
760 or ouch "couldn't move $dir/$sub into $h_64";
761 rmdir ".$h_32/$dir";
762 }
763 }
764 closedir DIR;
765 # if $ismbox is set, then $dir is a mailbox of it's own right
766 if ($ismbox) {
767 $h_32 = dir_hash_c_32($dir);
768 $h_64 = dir_hash_c_64($dir);
769 mkdir (".$h_64/$dir", 0755); # might already be there
770 opendir DIR, $dir;
771 while ($sub = readdir DIR) {
772 if ($sub =~ /^\./s) { next; }
773 if ("$h_32" eq "$h_64") {
774 rename ("$dir/$sub", ".$h_64/$dir/$sub")
775 or ouch "couldn't move $dir into $h_64";
776 } else {
777 mkdir (".$h_32/$dir", 0755); # might already be there
778 rename ("$dir/$sub", ".$h_32/$dir/$sub")
779 or ouch "couldn't move $dir into $h_32";
780 rename (".$h_32/$dir/$sub", ".$h_64/$dir/$sub")
781 or ouch "couldn't move $dir into $h_64";
782 rmdir ".$h_32/$dir";
783 }
784 }
785 closedir DIR;
786 }
787
788 rmdir $dir or print "\ncouldn't remove '$dir'??\n";
789 }
790 closedir PART;
791
792 foreach $i (@{$dirs}) {
793 rename (".$i", $i) or ouch "couldn't rename .$i to $i";
794 }
795 }
796 }
483 closedir(DIR);
484 }
485 }
486
487 remove_dir($dir);
488 }
489
490 sub tidy_up {
491 my $path = shift;
492 my $isspool = shift;
493 my $onemore = shift;
494
495
496 unless (not $fulldirhash and (not $isspool or $hashimapspool)) {
497 tidydir("$path/$_", $onemore) for @bdirs;
498 }
499 unless ($fulldirhash and (not $isspool or $hashimapspool)) {
500 tidydir("$path/$_", $onemore) for @fdirs;
501 }
502 }
0 /* Release cyrus-imapd-2.4.14 */
1 #define _CYRUS_VERSION "v2.4.14"
2 #define CYRUS_GITVERSION "104ce68b 2012-03-12"
0 /* Release cyrus-imapd-2.4.15 */
1 #define _CYRUS_VERSION "v2.4.15"
2 #define CYRUS_GITVERSION "6ea3d26c 2012-04-18"