Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: runtime/bin/directory_posix.cc

Issue 9139011: Handle EINTR on all IO operations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixed building on Mac OS Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/bin/eventhandler_linux.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | runtime/bin/eventhandler_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698