1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17 #include <config.h>
18 #include "maildir.h"
19 #include <unistd.h>
20 #include <string.h>
21 #include "ac/dirent.h"
22 #include "stat_fns.h"
23 #include "mystring/mystring.h"
24
rmdir(const mystring & n)25 static inline int rmdir(const mystring& n)
26 {
27 return rmdir(n.c_str());
28 }
29
mkdirp(const mystring & dirname,mode_t mode)30 int mkdirp(const mystring& dirname, mode_t mode)
31 {
32 if(is_dir(dirname.c_str()))
33 return 0;
34 int i = dirname.find_last('/');
35 if(i > 0) {
36 if(mkdirp(dirname.left(i), 0755))
37 return -1;
38 }
39 if(i != (int)dirname.length() - 1)
40 return mkdir(dirname.c_str(), mode);
41 return 0;
42 }
43
make_maildir(const mystring & dirname)44 bool make_maildir(const mystring& dirname)
45 {
46 if(mkdirp(dirname, 0700))
47 return false;
48 mystring curdir = dirname + "/cur";
49 if(mkdir(curdir.c_str(), 0755)) {
50 rmdir(dirname);
51 return false;
52 }
53 mystring newdir = dirname + "/new";
54 if(mkdir(newdir.c_str(), 0755)) {
55 rmdir(curdir);
56 rmdir(dirname);
57 return false;
58 }
59 mystring tmpdir = dirname + "/tmp";
60 if(mkdir(tmpdir.c_str(), 0755)) {
61 rmdir(newdir);
62 rmdir(curdir);
63 rmdir(dirname);
64 return false;
65 }
66 return true;
67 }
68
delete_directory(const mystring & dirname)69 bool delete_directory(const mystring& dirname)
70 {
71 int retry;
72 retry = 0;
73 do {
74 DIR* dir = opendir(dirname.c_str());
75 if(!dir)
76 return false;
77 while(dirent* entry = readdir(dir)) {
78 const char* name = entry->d_name;
79 if(name[0] == '.' &&
80 (NAMLEN(entry) == 1 ||
81 (name[1] == '.' && NAMLEN(entry) == 2)))
82 continue;
83 mystring fullname = dirname + "/";
84 fullname += mystring(name, NAMLEN(entry));
85 if(is_dir(fullname.c_str())) {
86 if(!delete_directory(fullname)) {
87 closedir(dir);
88 return false;
89 }
90 }
91 else if(unlink(fullname.c_str())) {
92 closedir(dir);
93 return false;
94 }
95 }
96 closedir(dir);
97 if (rmdir(dirname) == 0)
98 return true;
99 ++retry;
100 } while (retry < 3);
101 return false;
102 }
103