OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "bin/directory.h" | 5 #include "bin/directory.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <sys/param.h> | 9 #include <sys/param.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
11 #include <unistd.h> | 11 #include <unistd.h> |
(...skipping 20 matching lines...) Expand all Loading... |
32 bool recursive, | 32 bool recursive, |
33 Dart_Port dir_port, | 33 Dart_Port dir_port, |
34 Dart_Port file_port, | 34 Dart_Port file_port, |
35 Dart_Port done_port, | 35 Dart_Port done_port, |
36 Dart_Port error_port); | 36 Dart_Port error_port); |
37 | 37 |
38 | 38 |
39 static void ComputeFullPath(const char* dir_name, | 39 static void ComputeFullPath(const char* dir_name, |
40 char* path, | 40 char* path, |
41 int* path_length) { | 41 int* path_length) { |
42 char* abs_path = realpath(dir_name, path); | 42 char* abs_path; |
| 43 do { |
| 44 abs_path = realpath(dir_name, path); |
| 45 } while (abs_path == NULL && errno == EINTR); |
43 ASSERT(abs_path != NULL); | 46 ASSERT(abs_path != NULL); |
44 *path_length = strlen(path); | 47 *path_length = strlen(path); |
45 size_t written = snprintf(path + *path_length, | 48 size_t written = snprintf(path + *path_length, |
46 PATH_MAX - *path_length, | 49 PATH_MAX - *path_length, |
47 "%s", | 50 "%s", |
48 File::PathSeparator()); | 51 File::PathSeparator()); |
49 ASSERT(written == strlen(File::PathSeparator())); | 52 ASSERT(written == strlen(File::PathSeparator())); |
50 *path_length += written; | 53 *path_length += written; |
51 } | 54 } |
52 | 55 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 } | 124 } |
122 } | 125 } |
123 | 126 |
124 | 127 |
125 static bool ListRecursively(const char* dir_name, | 128 static bool ListRecursively(const char* dir_name, |
126 bool recursive, | 129 bool recursive, |
127 Dart_Port dir_port, | 130 Dart_Port dir_port, |
128 Dart_Port file_port, | 131 Dart_Port file_port, |
129 Dart_Port done_port, | 132 Dart_Port done_port, |
130 Dart_Port error_port) { | 133 Dart_Port error_port) { |
131 DIR* dir_pointer = opendir(dir_name); | 134 DIR* dir_pointer; |
| 135 do { |
| 136 dir_pointer = opendir(dir_name); |
| 137 } while (dir_pointer == NULL && errno == EINTR); |
132 if (dir_pointer == NULL) { | 138 if (dir_pointer == NULL) { |
133 PostError(error_port, "Directory listing failed for: ", dir_name, errno); | 139 PostError(error_port, "Directory listing failed for: ", dir_name, errno); |
134 return false; | 140 return false; |
135 } | 141 } |
136 | 142 |
137 // Compute full path for the directory currently being listed. | 143 // Compute full path for the directory currently being listed. |
138 char *path = static_cast<char*>(malloc(PATH_MAX)); | 144 char *path = static_cast<char*>(malloc(PATH_MAX)); |
139 ASSERT(path != NULL); | 145 ASSERT(path != NULL); |
140 int path_length = 0; | 146 int path_length = 0; |
141 ComputeFullPath(dir_name, path, &path_length); | 147 ComputeFullPath(dir_name, path, &path_length); |
142 | 148 |
143 // Iterated the directory and post the directories and files to the | 149 // Iterated the directory and post the directories and files to the |
144 // ports. | 150 // ports. |
145 int success = 0; | 151 int success = 0; |
146 bool listing_error = false; | 152 bool listing_error = false; |
147 dirent entry; | 153 dirent entry; |
148 dirent* result; | 154 dirent* result; |
149 while ((success = readdir_r(dir_pointer, &entry, &result)) == 0 && | 155 while ((success = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, |
| 156 &entry, |
| 157 &result))) == 0 && |
150 result != NULL && | 158 result != NULL && |
151 !listing_error) { | 159 !listing_error) { |
152 switch (entry.d_type) { | 160 switch (entry.d_type) { |
153 case DT_DIR: | 161 case DT_DIR: |
154 listing_error = listing_error || !HandleDir(entry.d_name, | 162 listing_error = listing_error || !HandleDir(entry.d_name, |
155 path, | 163 path, |
156 path_length, | 164 path_length, |
157 recursive, | 165 recursive, |
158 dir_port, | 166 dir_port, |
159 file_port, | 167 file_port, |
160 done_port, | 168 done_port, |
161 error_port); | 169 error_port); |
162 break; | 170 break; |
163 case DT_REG: | 171 case DT_REG: |
164 HandleFile(entry.d_name, path, path_length, file_port); | 172 HandleFile(entry.d_name, path, path_length, file_port); |
165 break; | 173 break; |
166 case DT_UNKNOWN: { | 174 case DT_UNKNOWN: { |
167 // On some file systems the entry type is not determined by | 175 // On some file systems the entry type is not determined by |
168 // readdir_r. For those we use lstat to determine the entry | 176 // readdir_r. For those we use lstat to determine the entry |
169 // type. | 177 // type. |
170 struct stat entry_info; | 178 struct stat entry_info; |
171 size_t written = snprintf(path + path_length, | 179 size_t written = snprintf(path + path_length, |
172 PATH_MAX - path_length, | 180 PATH_MAX - path_length, |
173 "%s", | 181 "%s", |
174 entry.d_name); | 182 entry.d_name); |
175 ASSERT(written == strlen(entry.d_name)); | 183 ASSERT(written == strlen(entry.d_name)); |
176 int lstat_success = lstat(path, &entry_info); | 184 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info)); |
177 if (lstat_success == -1) { | 185 if (lstat_success == -1) { |
178 listing_error = true; | 186 listing_error = true; |
179 PostError(error_port, "Directory listing failed for: ", path, errno); | 187 PostError(error_port, "Directory listing failed for: ", path, errno); |
180 break; | 188 break; |
181 } | 189 } |
182 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { | 190 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { |
183 listing_error = listing_error || !HandleDir(entry.d_name, | 191 listing_error = listing_error || !HandleDir(entry.d_name, |
184 path, | 192 path, |
185 path_length, | 193 path_length, |
186 recursive, | 194 recursive, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 error_port); | 234 error_port); |
227 if (done_port != 0) { | 235 if (done_port != 0) { |
228 Dart_Handle value = Dart_NewBoolean(completed); | 236 Dart_Handle value = Dart_NewBoolean(completed); |
229 Dart_Post(done_port, value); | 237 Dart_Post(done_port, value); |
230 } | 238 } |
231 } | 239 } |
232 | 240 |
233 | 241 |
234 Directory::ExistsResult Directory::Exists(const char* dir_name) { | 242 Directory::ExistsResult Directory::Exists(const char* dir_name) { |
235 struct stat entry_info; | 243 struct stat entry_info; |
236 int lstat_success = lstat(dir_name, &entry_info); | 244 int lstat_success = TEMP_FAILURE_RETRY(lstat(dir_name, &entry_info)); |
237 if (lstat_success == 0) { | 245 if (lstat_success == 0) { |
238 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { | 246 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { |
239 return EXISTS; | 247 return EXISTS; |
240 } else { | 248 } else { |
241 return DOES_NOT_EXIST; | 249 return DOES_NOT_EXIST; |
242 } | 250 } |
243 } else { | 251 } else { |
244 if (errno == EACCES || | 252 if (errno == EACCES || |
245 errno == EBADF || | 253 errno == EBADF || |
246 errno == EFAULT || | 254 errno == EFAULT || |
247 errno == ENOMEM || | 255 errno == ENOMEM || |
248 errno == EOVERFLOW) { | 256 errno == EOVERFLOW) { |
249 // Search permissions denied for one of the directories in the | 257 // Search permissions denied for one of the directories in the |
250 // path or a low level error occured. We do not know if the | 258 // path or a low level error occured. We do not know if the |
251 // directory exists. | 259 // directory exists. |
252 return UNKNOWN; | 260 return UNKNOWN; |
253 } | 261 } |
254 ASSERT(errno == ELOOP || | 262 ASSERT(errno == ELOOP || |
255 errno == ENAMETOOLONG || | 263 errno == ENAMETOOLONG || |
256 errno == ENOENT || | 264 errno == ENOENT || |
257 errno == ENOTDIR); | 265 errno == ENOTDIR); |
258 return DOES_NOT_EXIST; | 266 return DOES_NOT_EXIST; |
259 } | 267 } |
260 } | 268 } |
261 | 269 |
262 | 270 |
263 bool Directory::Create(const char* dir_name) { | 271 bool Directory::Create(const char* dir_name) { |
264 // Create the directory with the permissions specified by the | 272 // Create the directory with the permissions specified by the |
265 // process umask. | 273 // process umask. |
266 return (mkdir(dir_name, 0777) == 0); | 274 return (TEMP_FAILURE_RETRY(mkdir(dir_name, 0777)) == 0); |
267 } | 275 } |
268 | 276 |
269 | 277 |
270 int Directory::CreateTemp(const char* const_template, | 278 int Directory::CreateTemp(const char* const_template, |
271 char** path, | 279 char** path, |
272 char* os_error_message, | 280 char* os_error_message, |
273 int os_error_message_len) { | 281 int os_error_message_len) { |
274 // Returns a new, unused directory name, modifying the contents of | 282 // Returns a new, unused directory name, modifying the contents of |
275 // dir_template. Creates the directory with the permissions specified | 283 // dir_template. Creates the directory with the permissions specified |
276 // by the process umask. | 284 // by the process umask. |
277 // The return value must be freed by the caller. | 285 // The return value must be freed by the caller. |
278 *path = static_cast<char*>(malloc(PATH_MAX + 1)); | 286 *path = static_cast<char*>(malloc(PATH_MAX + 1)); |
279 SafeStrNCpy(*path, const_template, PATH_MAX + 1); | 287 SafeStrNCpy(*path, const_template, PATH_MAX + 1); |
280 int path_length = strlen(*path); | 288 int path_length = strlen(*path); |
281 if (path_length > 0) { | 289 if (path_length > 0) { |
282 if ((*path)[path_length - 1] == '/') { | 290 if ((*path)[path_length - 1] == '/') { |
283 snprintf(*path + path_length, PATH_MAX - path_length, "temp_dir_XXXXXX"); | 291 snprintf(*path + path_length, PATH_MAX - path_length, "temp_dir_XXXXXX"); |
284 } else { | 292 } else { |
285 snprintf(*path + path_length, PATH_MAX - path_length, "XXXXXX"); | 293 snprintf(*path + path_length, PATH_MAX - path_length, "XXXXXX"); |
286 } | 294 } |
287 } else { | 295 } else { |
288 snprintf(*path, PATH_MAX, "/tmp/temp_dir1_XXXXXX"); | 296 snprintf(*path, PATH_MAX, "/tmp/temp_dir1_XXXXXX"); |
289 } | 297 } |
290 char* result = mkdtemp(*path); | 298 char* result; |
| 299 do { |
| 300 result = mkdtemp(*path); |
| 301 } while (result == NULL && errno == EINTR); |
291 if (result == NULL) { | 302 if (result == NULL) { |
292 SetOsErrorMessage(os_error_message, os_error_message_len); | 303 SetOsErrorMessage(os_error_message, os_error_message_len); |
293 free(*path); | 304 free(*path); |
294 *path = NULL; | 305 *path = NULL; |
295 return errno; | 306 return errno; |
296 } | 307 } |
297 return 0; | 308 return 0; |
298 } | 309 } |
299 | 310 |
300 | 311 |
301 bool Directory::Delete(const char* dir_name) { | 312 bool Directory::Delete(const char* dir_name) { |
302 return (rmdir(dir_name) == 0); | 313 return (TEMP_FAILURE_RETRY(rmdir(dir_name)) == 0); |
303 } | 314 } |
OLD | NEW |