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