Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib/unlink-directory.c @ 1329:ae229b7acb4c HEAD
Mailbox names are now sent through imap-quoter instead of just escaping it.
This means that mailbox names that would require escapes are instead sent
as literals now.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 02 Apr 2003 05:05:38 +0300 |
parents | 9833f1b94f25 |
children | 22495f001acc |
rev | line source |
---|---|
0 | 1 /* |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
2 unlink-directory.c : Safely unlink directory with everything under it. |
0 | 3 |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
4 Copyright (c) 2002-2003 Timo Sirainen |
0 | 5 |
6 Permission is hereby granted, free of charge, to any person obtaining | |
7 a copy of this software and associated documentation files (the | |
8 "Software"), to deal in the Software without restriction, including | |
9 without limitation the rights to use, copy, modify, merge, publish, | |
10 distribute, sublicense, and/or sell copies of the Software, and to | |
11 permit persons to whom the Software is furnished to do so, subject to | |
12 the following conditions: | |
13 | |
14 The above copyright notice and this permission notice shall be | |
15 included in all copies or substantial portions of the Software. | |
16 | |
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
20 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
22 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
23 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
24 */ | |
25 | |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
26 #define _GNU_SOURCE /* for O_NOFOLLOW with Linux */ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
27 |
0 | 28 #include "lib.h" |
29 #include "unlink-directory.h" | |
30 | |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
31 #include <fcntl.h> |
0 | 32 #include <unistd.h> |
33 #include <dirent.h> | |
34 #include <sys/stat.h> | |
35 | |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
36 #define close_save_errno(fd) \ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
37 STMT_START { \ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
38 old_errno = errno; \ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
39 (void)close(fd); \ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
40 errno = old_errno; \ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
41 } STMT_END |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
42 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
43 static int unlink_directory_r(const char *dir) |
0 | 44 { |
45 DIR *dirp; | |
46 struct dirent *d; | |
47 struct stat st; | |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
48 int dir_fd, old_errno; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
49 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
50 /* There's a bit tricky race condition with recursive deletion. |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
51 Suppose this happens: |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
52 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
53 lstat(dir, ..) -> OK, it's a directory |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
54 // attacker deletes dir, replaces it with symlink to / |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
55 opendir(dir) -> it actually opens / |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
56 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
57 Most portable solution is to lstat() the dir, chdir() there, then |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
58 check that "." points to same device/inode as we originally |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
59 lstat()ed. This assumes that the device has usable inodes, most |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
60 should except for some NFS implementations. |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
61 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
62 Filesystems may also reassign a deleted inode to another file |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
63 immediately after it's deleted. That in theory makes it possible to |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
64 exploit this race to delete the new directory. However, the new |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
65 inode is quite unlikely to be any important directory, and attacker |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
66 is quite unlikely to find out which directory even got the inode. |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
67 Maybe with some setuid program or daemon interaction something could |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
68 come out of it though. |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
69 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
70 Another less portable solution is to fchdir(open(dir, O_NOFOLLOW)). |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
71 This should be completely safe. |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
72 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
73 The actual file deletion also has to be done relative to current |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
74 directory, to make sure that the whole directory structure isn't |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
75 replaced with another one while we're deleting it. Going back to |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
76 parent directory isn't too easy either - safest (and easiest) way |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
77 again is to open() the directory and fchdir() back there. |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
78 */ |
0 | 79 |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
80 #ifdef O_NOFOLLOW |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
81 dir_fd = open(dir, O_RDONLY | O_NOFOLLOW); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
82 if (dir_fd == -1) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
83 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
84 #else |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
85 struct stat st2; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
86 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
87 if (lstat(dir, &st) < 0) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
88 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
89 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
90 if (!S_ISDIR(st.st_mode)) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
91 errno = ENOTDIR; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
92 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
93 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
94 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
95 dir_fd = open(dir, O_RDONLY); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
96 if (dir_fd == -1) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
97 return -1; |
0 | 98 |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
99 if (fstat(dir_fd, &st2) < 0) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
100 close_save_errno(dir_fd); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
101 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
102 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
103 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
104 if (st.st_ino != st2.st_ino || |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
105 !CMP_DEV_T(st.st_dev, st2.st_dev)) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
106 /* directory was just replaced with something else. */ |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
107 (void)close(dir_fd); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
108 errno = ENOTDIR; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
109 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
110 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
111 #endif |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
112 if (fchdir(dir_fd) < 0) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
113 close_save_errno(dir_fd); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
114 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
115 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
116 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
117 dirp = opendir("."); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
118 if (dirp == NULL) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
119 close_save_errno(dir_fd); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
120 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
121 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
122 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
123 errno = 0; |
0 | 124 while ((d = readdir(dirp)) != NULL) { |
125 if (d->d_name[0] == '.' && | |
126 (d->d_name[1] == '\0' || | |
127 (d->d_name[1] == '.' && d->d_name[2] == '\0'))) { | |
128 /* skip . and .. */ | |
129 continue; | |
130 } | |
131 | |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
132 if (unlink(d->d_name) == -1 && errno != ENOENT) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
133 old_errno = errno; |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
134 |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
135 if (lstat(d->d_name, &st) == 0 && S_ISDIR(st.st_mode)) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
136 if (unlink_directory_r(d->d_name) < 0) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
137 if (errno != ENOENT) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
138 break; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
139 errno = 0; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
140 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
141 if (fchdir(dir_fd) < 0) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
142 break; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
143 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
144 if (rmdir(d->d_name) < 0) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
145 if (errno != ENOENT) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
146 break; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
147 errno = 0; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
148 } |
0 | 149 } else { |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
150 /* so it wasn't a directory */ |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
151 errno = old_errno; |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
152 break; |
0 | 153 } |
154 } | |
155 } | |
156 | |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
157 (void)close(dir_fd); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
158 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
159 old_errno = errno; |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
817
diff
changeset
|
160 if (closedir(dirp) < 0) |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
817
diff
changeset
|
161 return -1; |
0 | 162 |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
163 if (old_errno != 0) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
164 errno = old_errno; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
165 return -1; |
822
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
817
diff
changeset
|
166 } |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
817
diff
changeset
|
167 |
5101f8bf2368
If used base/login directories exist already, make sure they're with correct
Timo Sirainen <tss@iki.fi>
parents:
817
diff
changeset
|
168 return 0; |
0 | 169 } |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
170 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
171 int unlink_directory(const char *dir, int unlink_dir) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
172 { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
173 int fd, ret; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
174 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
175 fd = open(".", O_RDONLY); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
176 if (fd == -1) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
177 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
178 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
179 ret = unlink_directory_r(dir); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
180 if (ret < 0 && errno == ENOENT) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
181 ret = 0; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
182 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
183 if (fchdir(fd) < 0) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
184 i_fatal("unlink_directory(%s): " |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
185 "Can't fchdir() back to our original dir: %m", dir); |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
186 } |
1249 | 187 (void)close(fd); |
1243
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
188 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
189 if (unlink_dir) { |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
190 if (rmdir(dir) < 0 && errno != ENOENT) |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
191 return -1; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
192 } |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
193 |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
194 return ret; |
478471737964
unlink_directory() is now (hopefully) race-condition free.
Timo Sirainen <tss@iki.fi>
parents:
822
diff
changeset
|
195 } |