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

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

Issue 1781883002: Fixes some memory leaks in //runtime/bin (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix tests on Windows Created 4 years, 9 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
« no previous file with comments | « runtime/bin/directory_android.cc ('k') | runtime/bin/directory_macos.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) 2012, 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 "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_LINUX) 6 #if defined(TARGET_OS_LINUX)
7 7
8 #include "bin/directory.h" 8 #include "bin/directory.h"
9 9
10 #include <dirent.h> // NOLINT 10 #include <dirent.h> // NOLINT
11 #include <errno.h> // NOLINT 11 #include <errno.h> // NOLINT
12 #include <stdlib.h> // NOLINT 12 #include <stdlib.h> // NOLINT
13 #include <string.h> // NOLINT 13 #include <string.h> // NOLINT
14 #include <sys/param.h> // NOLINT 14 #include <sys/param.h> // NOLINT
15 #include <sys/stat.h> // NOLINT 15 #include <sys/stat.h> // NOLINT
16 #include <unistd.h> // NOLINT 16 #include <unistd.h> // NOLINT
17 17
18 #include "platform/signal_blocker.h" 18 #include "bin/dartutils.h"
19 #include "bin/file.h" 19 #include "bin/file.h"
20 #include "bin/platform.h" 20 #include "bin/platform.h"
21 21 #include "platform/signal_blocker.h"
22 22
23 namespace dart { 23 namespace dart {
24 namespace bin { 24 namespace bin {
25 25
26 PathBuffer::PathBuffer() : length_(0) {
27 data_ = calloc(PATH_MAX + 1, sizeof(char)); // NOLINT
28 }
26 29
27 PathBuffer::PathBuffer() : length_(0) { 30
28 data_ = calloc(PATH_MAX + 1, sizeof(char)); // NOLINT 31 PathBuffer::~PathBuffer() {
32 free(data_);
29 } 33 }
30 34
35
31 bool PathBuffer::AddW(const wchar_t* name) { 36 bool PathBuffer::AddW(const wchar_t* name) {
32 UNREACHABLE(); 37 UNREACHABLE();
33 return false; 38 return false;
34 } 39 }
35 40
41
36 char* PathBuffer::AsString() const { 42 char* PathBuffer::AsString() const {
37 return reinterpret_cast<char*>(data_); 43 return reinterpret_cast<char*>(data_);
38 } 44 }
39 45
46
40 wchar_t* PathBuffer::AsStringW() const { 47 wchar_t* PathBuffer::AsStringW() const {
41 UNREACHABLE(); 48 UNREACHABLE();
42 return NULL; 49 return NULL;
43 } 50 }
44 51
52
53 const char* PathBuffer::AsScopedString() const {
54 return DartUtils::ScopedCopyCString(AsString());
55 }
56
57
45 bool PathBuffer::Add(const char* name) { 58 bool PathBuffer::Add(const char* name) {
46 char* data = AsString(); 59 char* data = AsString();
47 int written = snprintf(data + length_, 60 int written = snprintf(data + length_,
48 PATH_MAX - length_, 61 PATH_MAX - length_,
49 "%s", 62 "%s",
50 name); 63 name);
51 data[PATH_MAX] = '\0'; 64 data[PATH_MAX] = '\0';
52 if (written <= PATH_MAX - length_ && 65 if ((written <= PATH_MAX - length_) &&
53 written >= 0 && 66 (written >= 0) &&
54 static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1)) { 67 (static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1))) {
55 length_ += written; 68 length_ += written;
56 return true; 69 return true;
57 } else { 70 } else {
58 errno = ENAMETOOLONG; 71 errno = ENAMETOOLONG;
59 return false; 72 return false;
60 } 73 }
61 } 74 }
62 75
63 void PathBuffer::Reset(int new_length) { 76
77 void PathBuffer::Reset(intptr_t new_length) {
64 length_ = new_length; 78 length_ = new_length;
65 AsString()[length_] = '\0'; 79 AsString()[length_] = '\0';
66 } 80 }
67 81
68 82
69 // A linked list of symbolic links, with their unique file system identifiers. 83 // A linked list of symbolic links, with their unique file system identifiers.
70 // These are scanned to detect loops while doing a recursive directory listing. 84 // These are scanned to detect loops while doing a recursive directory listing.
71 struct LinkList { 85 struct LinkList {
72 dev_t dev; 86 dev_t dev;
73 ino64_t ino; 87 ino64_t ino;
74 LinkList* next; 88 LinkList* next;
75 }; 89 };
76 90
77 91
78 ListType DirectoryListingEntry::Next(DirectoryListing* listing) { 92 ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
79 if (done_) { 93 if (done_) {
80 return kListDone; 94 return kListDone;
81 } 95 }
82 96
83 if (lister_ == 0) { 97 if (lister_ == 0) {
84 do { 98 do {
85 lister_ = reinterpret_cast<intptr_t>( 99 lister_ = reinterpret_cast<intptr_t>(
86 opendir(listing->path_buffer().AsString())); 100 opendir(listing->path_buffer().AsString()));
87 } while (lister_ == 0 && errno == EINTR); 101 } while ((lister_ == 0) && (errno == EINTR));
88 102
89 if (lister_ == 0) { 103 if (lister_ == 0) {
90 done_ = true; 104 done_ = true;
91 return kListError; 105 return kListError;
92 } 106 }
93 if (parent_ != NULL) { 107 if (parent_ != NULL) {
94 if (!listing->path_buffer().Add(File::PathSeparator())) { 108 if (!listing->path_buffer().Add(File::PathSeparator())) {
95 return kListError; 109 return kListError;
96 } 110 }
97 } 111 }
98 path_length_ = listing->path_buffer().length(); 112 path_length_ = listing->path_buffer().length();
99 } 113 }
100 // Reset. 114 // Reset.
101 listing->path_buffer().Reset(path_length_); 115 listing->path_buffer().Reset(path_length_);
102 ResetLink(); 116 ResetLink();
103 117
104 // Iterate the directory and post the directories and files to the 118 // Iterate the directory and post the directories and files to the
105 // ports. 119 // ports.
106 int status = 0; 120 int status = 0;
107 dirent entry; 121 dirent entry;
108 dirent* result; 122 dirent* result;
109 if ((status = NO_RETRY_EXPECTED(readdir_r(reinterpret_cast<DIR*>(lister_), 123 status = NO_RETRY_EXPECTED(readdir_r(
110 &entry, 124 reinterpret_cast<DIR*>(lister_), &entry, &result));
111 &result))) == 0 && 125 if ((status == 0) && (result != NULL)) {
112 result != NULL) {
113 if (!listing->path_buffer().Add(entry.d_name)) { 126 if (!listing->path_buffer().Add(entry.d_name)) {
114 done_ = true; 127 done_ = true;
115 return kListError; 128 return kListError;
116 } 129 }
117 switch (entry.d_type) { 130 switch (entry.d_type) {
118 case DT_DIR: 131 case DT_DIR:
119 if (strcmp(entry.d_name, ".") == 0) return Next(listing); 132 if ((strcmp(entry.d_name, ".") == 0) ||
120 if (strcmp(entry.d_name, "..") == 0) return Next(listing); 133 (strcmp(entry.d_name, "..") == 0)) {
134 return Next(listing);
135 }
121 return kListDirectory; 136 return kListDirectory;
122 case DT_REG: 137 case DT_REG:
123 return kListFile; 138 return kListFile;
124 case DT_LNK: 139 case DT_LNK:
125 if (!listing->follow_links()) { 140 if (!listing->follow_links()) {
126 return kListLink; 141 return kListLink;
127 } 142 }
128 // Else fall through to next case. 143 // Else fall through to next case.
129 // Fall through. 144 // Fall through.
130 case DT_UNKNOWN: { 145 case DT_UNKNOWN: {
131 // On some file systems the entry type is not determined by 146 // On some file systems the entry type is not determined by
132 // readdir_r. For those and for links we use stat to determine 147 // readdir_r. For those and for links we use stat to determine
133 // the actual entry type. Notice that stat returns the type of 148 // the actual entry type. Notice that stat returns the type of
134 // the file pointed to. 149 // the file pointed to.
135 struct stat64 entry_info; 150 struct stat64 entry_info;
136 int stat_success; 151 int stat_success;
137 stat_success = TEMP_FAILURE_RETRY( 152 stat_success = TEMP_FAILURE_RETRY(
138 lstat64(listing->path_buffer().AsString(), &entry_info)); 153 lstat64(listing->path_buffer().AsString(), &entry_info));
139 if (stat_success == -1) { 154 if (stat_success == -1) {
140 return kListError; 155 return kListError;
141 } 156 }
142 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { 157 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) {
143 // Check to see if we are in a loop created by a symbolic link. 158 // Check to see if we are in a loop created by a symbolic link.
144 LinkList current_link = { entry_info.st_dev, 159 LinkList current_link = { entry_info.st_dev,
145 entry_info.st_ino, 160 entry_info.st_ino,
146 link_ }; 161 link_ };
147 LinkList* previous = link_; 162 LinkList* previous = link_;
148 while (previous != NULL) { 163 while (previous != NULL) {
149 if (previous->dev == current_link.dev && 164 if ((previous->dev == current_link.dev) &&
150 previous->ino == current_link.ino) { 165 (previous->ino == current_link.ino)) {
151 // Report the looping link as a link, rather than following it. 166 // Report the looping link as a link, rather than following it.
152 return kListLink; 167 return kListLink;
153 } 168 }
154 previous = previous->next; 169 previous = previous->next;
155 } 170 }
156 stat_success = TEMP_FAILURE_RETRY( 171 stat_success = TEMP_FAILURE_RETRY(
157 stat64(listing->path_buffer().AsString(), &entry_info)); 172 stat64(listing->path_buffer().AsString(), &entry_info));
158 if (stat_success == -1) { 173 if (stat_success == -1) {
159 // Report a broken link as a link, even if follow_links is true. 174 // Report a broken link as a link, even if follow_links is true.
160 return kListLink; 175 return kListLink;
161 } 176 }
162 if (S_ISDIR(entry_info.st_mode)) { 177 if (S_ISDIR(entry_info.st_mode)) {
163 // Recurse into the subdirectory with current_link added to the 178 // Recurse into the subdirectory with current_link added to the
164 // linked list of seen file system links. 179 // linked list of seen file system links.
165 link_ = new LinkList(current_link); 180 link_ = new LinkList(current_link);
166 if (strcmp(entry.d_name, ".") == 0) return Next(listing); 181 if ((strcmp(entry.d_name, ".") == 0) ||
167 if (strcmp(entry.d_name, "..") == 0) return Next(listing); 182 (strcmp(entry.d_name, "..") == 0)) {
183 return Next(listing);
184 }
168 return kListDirectory; 185 return kListDirectory;
169 } 186 }
170 } 187 }
171 if (S_ISDIR(entry_info.st_mode)) { 188 if (S_ISDIR(entry_info.st_mode)) {
172 if (strcmp(entry.d_name, ".") == 0) return Next(listing); 189 if ((strcmp(entry.d_name, ".") == 0) ||
173 if (strcmp(entry.d_name, "..") == 0) return Next(listing); 190 (strcmp(entry.d_name, "..") == 0)) {
191 return Next(listing);
192 }
174 return kListDirectory; 193 return kListDirectory;
175 } else if (S_ISREG(entry_info.st_mode)) { 194 } else if (S_ISREG(entry_info.st_mode)) {
176 return kListFile; 195 return kListFile;
177 } else if (S_ISLNK(entry_info.st_mode)) { 196 } else if (S_ISLNK(entry_info.st_mode)) {
178 return kListLink; 197 return kListLink;
179 } 198 }
180 } 199 }
181 200
182 default: 201 default:
183 break; 202 break;
(...skipping 12 matching lines...) Expand all
196 215
197 DirectoryListingEntry::~DirectoryListingEntry() { 216 DirectoryListingEntry::~DirectoryListingEntry() {
198 ResetLink(); 217 ResetLink();
199 if (lister_ != 0) { 218 if (lister_ != 0) {
200 VOID_NO_RETRY_EXPECTED(closedir(reinterpret_cast<DIR*>(lister_))); 219 VOID_NO_RETRY_EXPECTED(closedir(reinterpret_cast<DIR*>(lister_)));
201 } 220 }
202 } 221 }
203 222
204 223
205 void DirectoryListingEntry::ResetLink() { 224 void DirectoryListingEntry::ResetLink() {
206 if (link_ != NULL && (parent_ == NULL || parent_->link_ != link_)) { 225 if ((link_ != NULL) && ((parent_ == NULL) || (parent_->link_ != link_))) {
207 delete link_; 226 delete link_;
208 link_ = NULL; 227 link_ = NULL;
209 } 228 }
210 if (parent_ != NULL) { 229 if (parent_ != NULL) {
211 link_ = parent_->link_; 230 link_ = parent_->link_;
212 } 231 }
213 } 232 }
214 233
215 234
216 static bool DeleteRecursively(PathBuffer* path); 235 static bool DeleteRecursively(PathBuffer* path);
217 236
218 237
219 static bool DeleteFile(char* file_name, 238 static bool DeleteFile(char* file_name,
220 PathBuffer* path) { 239 PathBuffer* path) {
221 return path->Add(file_name) && 240 return path->Add(file_name) &&
222 NO_RETRY_EXPECTED(unlink(path->AsString())) == 0; 241 (NO_RETRY_EXPECTED(unlink(path->AsString())) == 0);
223 } 242 }
224 243
225 244
226 static bool DeleteDir(char* dir_name, 245 static bool DeleteDir(char* dir_name,
227 PathBuffer* path) { 246 PathBuffer* path) {
228 if (strcmp(dir_name, ".") == 0) return true; 247 if ((strcmp(dir_name, ".") == 0) || (strcmp(dir_name, "..") == 0)) {
229 if (strcmp(dir_name, "..") == 0) return true; 248 return true;
249 }
230 return path->Add(dir_name) && DeleteRecursively(path); 250 return path->Add(dir_name) && DeleteRecursively(path);
231 } 251 }
232 252
233 253
234 static bool DeleteRecursively(PathBuffer* path) { 254 static bool DeleteRecursively(PathBuffer* path) {
235 // Do not recurse into links for deletion. Instead delete the link. 255 // Do not recurse into links for deletion. Instead delete the link.
236 // If it's a file, delete it. 256 // If it's a file, delete it.
237 struct stat64 st; 257 struct stat64 st;
238 if (TEMP_FAILURE_RETRY(lstat64(path->AsString(), &st)) == -1) { 258 if (TEMP_FAILURE_RETRY(lstat64(path->AsString(), &st)) == -1) {
239 return false; 259 return false;
240 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { 260 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
241 return (NO_RETRY_EXPECTED(unlink(path->AsString())) == 0); 261 return (NO_RETRY_EXPECTED(unlink(path->AsString())) == 0);
242 } 262 }
243 263
244 if (!path->Add(File::PathSeparator())) return false; 264 if (!path->Add(File::PathSeparator())) {
265 return false;
266 }
245 267
246 // Not a link. Attempt to open as a directory and recurse into the 268 // Not a link. Attempt to open as a directory and recurse into the
247 // directory. 269 // directory.
248 DIR* dir_pointer; 270 DIR* dir_pointer;
249 do { 271 do {
250 dir_pointer = opendir(path->AsString()); 272 dir_pointer = opendir(path->AsString());
251 } while (dir_pointer == NULL && errno == EINTR); 273 } while ((dir_pointer == NULL) && (errno == EINTR));
252 if (dir_pointer == NULL) { 274 if (dir_pointer == NULL) {
253 return false; 275 return false;
254 } 276 }
255 277
256 // Iterate the directory and delete all files and directories. 278 // Iterate the directory and delete all files and directories.
257 int path_length = path->length(); 279 int path_length = path->length();
258 dirent entry; 280 dirent entry;
259 dirent* result; 281 dirent* result;
260 while (NO_RETRY_EXPECTED(readdir_r(dir_pointer, &entry, &result)) == 0) { 282 while (NO_RETRY_EXPECTED(readdir_r(dir_pointer, &entry, &result)) == 0) {
261 if (result == NULL) { 283 if (result == NULL) {
262 // End of directory. 284 // End of directory.
263 return NO_RETRY_EXPECTED(closedir(dir_pointer)) == 0 && 285 return (NO_RETRY_EXPECTED(closedir(dir_pointer)) == 0) &&
264 NO_RETRY_EXPECTED(remove(path->AsString())) == 0; 286 (NO_RETRY_EXPECTED(remove(path->AsString())) == 0);
265 } 287 }
266 bool ok = false; 288 bool ok = false;
267 switch (entry.d_type) { 289 switch (entry.d_type) {
268 case DT_DIR: 290 case DT_DIR:
269 ok = DeleteDir(entry.d_name, path); 291 ok = DeleteDir(entry.d_name, path);
270 break; 292 break;
271 case DT_REG: 293 case DT_REG:
272 case DT_LNK: 294 case DT_LNK:
273 // Treat all links as files. This will delete the link which 295 // Treat all links as files. This will delete the link which
274 // is what we want no matter if the link target is a file or a 296 // is what we want no matter if the link target is a file or a
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 Directory::ExistsResult Directory::Exists(const char* dir_name) { 339 Directory::ExistsResult Directory::Exists(const char* dir_name) {
318 struct stat64 entry_info; 340 struct stat64 entry_info;
319 int success = TEMP_FAILURE_RETRY(stat64(dir_name, &entry_info)); 341 int success = TEMP_FAILURE_RETRY(stat64(dir_name, &entry_info));
320 if (success == 0) { 342 if (success == 0) {
321 if (S_ISDIR(entry_info.st_mode)) { 343 if (S_ISDIR(entry_info.st_mode)) {
322 return EXISTS; 344 return EXISTS;
323 } else { 345 } else {
324 return DOES_NOT_EXIST; 346 return DOES_NOT_EXIST;
325 } 347 }
326 } else { 348 } else {
327 if (errno == EACCES || 349 if ((errno == EACCES) ||
328 errno == EBADF || 350 (errno == EBADF) ||
329 errno == EFAULT || 351 (errno == EFAULT) ||
330 errno == ENOMEM || 352 (errno == ENOMEM) ||
331 errno == EOVERFLOW) { 353 (errno == EOVERFLOW)) {
332 // Search permissions denied for one of the directories in the 354 // Search permissions denied for one of the directories in the
333 // path or a low level error occured. We do not know if the 355 // path or a low level error occured. We do not know if the
334 // directory exists. 356 // directory exists.
335 return UNKNOWN; 357 return UNKNOWN;
336 } 358 }
337 ASSERT(errno == ELOOP || 359 ASSERT((errno == ELOOP) ||
338 errno == ENAMETOOLONG || 360 (errno == ENAMETOOLONG) ||
339 errno == ENOENT || 361 (errno == ENOENT) ||
340 errno == ENOTDIR); 362 (errno == ENOTDIR));
341 return DOES_NOT_EXIST; 363 return DOES_NOT_EXIST;
342 } 364 }
343 } 365 }
344 366
345 367
346 char* Directory::Current() { 368 char* Directory::CurrentNoScope() {
347 size_t size = PATH_MAX; 369 char buffer[PATH_MAX];
348 char* buffer = NULL; 370 if (getcwd(buffer, PATH_MAX) == NULL) {
349 for (char* result = NULL; result == NULL; size *= 2) { 371 return NULL;
350 if ((buffer = reinterpret_cast<char*>(realloc(buffer, size))) == NULL) {
351 return NULL;
352 }
353 result = getcwd(buffer, size);
354 if (result == NULL && errno != ERANGE) {
355 return NULL;
356 }
357 } 372 }
358 return buffer; 373 return strdup(buffer);
359 } 374 }
360 375
361 376
377 const char* Directory::Current() {
378 char buffer[PATH_MAX];
379 if (getcwd(buffer, PATH_MAX) == NULL) {
380 return NULL;
381 }
382 return DartUtils::ScopedCopyCString(buffer);
383 }
384
385
362 bool Directory::SetCurrent(const char* path) { 386 bool Directory::SetCurrent(const char* path) {
363 return NO_RETRY_EXPECTED(chdir(path)) == 0; 387 return NO_RETRY_EXPECTED(chdir(path)) == 0;
364 } 388 }
365 389
366 390
367 bool Directory::Create(const char* dir_name) { 391 bool Directory::Create(const char* dir_name) {
368 // Create the directory with the permissions specified by the 392 // Create the directory with the permissions specified by the
369 // process umask. 393 // process umask.
370 int result = NO_RETRY_EXPECTED(mkdir(dir_name, 0777)); 394 int result = NO_RETRY_EXPECTED(mkdir(dir_name, 0777));
371 // If the directory already exists, treat it as a success. 395 // If the directory already exists, treat it as a success.
372 if (result == -1 && errno == EEXIST) { 396 if ((result == -1) && (errno == EEXIST)) {
373 return (Exists(dir_name) == EXISTS); 397 return (Exists(dir_name) == EXISTS);
374 } 398 }
375 return (result == 0); 399 return (result == 0);
376 } 400 }
377 401
378 402
379 char* Directory::SystemTemp() { 403 const char* Directory::SystemTemp() {
404 PathBuffer path;
380 const char* temp_dir = getenv("TMPDIR"); 405 const char* temp_dir = getenv("TMPDIR");
381 if (temp_dir == NULL) { 406 if (temp_dir == NULL) {
382 temp_dir = getenv("TMP"); 407 temp_dir = getenv("TMP");
383 } 408 }
384 if (temp_dir == NULL) { 409 if (temp_dir == NULL) {
385 temp_dir = "/tmp"; 410 temp_dir = "/tmp";
386 } 411 }
387 char* result = strdup(temp_dir); 412 if (!path.Add(temp_dir)) {
413 return NULL;
414 }
415
388 // Remove any trailing slash. 416 // Remove any trailing slash.
417 char* result = path.AsString();
389 int length = strlen(result); 418 int length = strlen(result);
390 if (length > 1 && result[length - 1] == '/') { 419 if ((length > 1) && (result[length - 1] == '/')) {
391 result[length - 1] = '\0'; 420 result[length - 1] = '\0';
392 } 421 }
393 return result; 422 return path.AsScopedString();
394 } 423 }
395 424
396 425
397 char* Directory::CreateTemp(const char* prefix) { 426 const char* Directory::CreateTemp(const char* prefix) {
398 // Returns a new, unused directory name, adding characters to the end 427 // Returns a new, unused directory name, adding characters to the end
399 // of prefix. Creates the directory with the permissions specified 428 // of prefix. Creates the directory with the permissions specified
400 // by the process umask. 429 // by the process umask.
401 // The return value must be freed by the caller. 430 // The return value is Dart_ScopeAllocated.
402 PathBuffer path; 431 PathBuffer path;
403 path.Add(prefix); 432 if (!path.Add(prefix)) {
433 return NULL;
434 }
404 if (!path.Add("XXXXXX")) { 435 if (!path.Add("XXXXXX")) {
405 // Pattern has overflowed. 436 // Pattern has overflowed.
406 return NULL; 437 return NULL;
407 } 438 }
408 char* result; 439 char* result;
409 do { 440 do {
410 result = mkdtemp(path.AsString()); 441 result = mkdtemp(path.AsString());
411 } while (result == NULL && errno == EINTR); 442 } while ((result == NULL) && (errno == EINTR));
412 if (result == NULL) { 443 if (result == NULL) {
413 return NULL; 444 return NULL;
414 } 445 }
415 return strdup(result); 446 return path.AsScopedString();
416 } 447 }
417 448
418 449
419 bool Directory::Delete(const char* dir_name, bool recursive) { 450 bool Directory::Delete(const char* dir_name, bool recursive) {
420 if (!recursive) { 451 if (!recursive) {
421 if (File::GetType(dir_name, false) == File::kIsLink && 452 if ((File::GetType(dir_name, false) == File::kIsLink) &&
422 File::GetType(dir_name, true) == File::kIsDirectory) { 453 (File::GetType(dir_name, true) == File::kIsDirectory)) {
423 return NO_RETRY_EXPECTED(unlink(dir_name)) == 0; 454 return NO_RETRY_EXPECTED(unlink(dir_name)) == 0;
424 } 455 }
425 return NO_RETRY_EXPECTED(rmdir(dir_name)) == 0; 456 return NO_RETRY_EXPECTED(rmdir(dir_name)) == 0;
426 } else { 457 } else {
427 PathBuffer path; 458 PathBuffer path;
428 if (!path.Add(dir_name)) { 459 if (!path.Add(dir_name)) {
429 return false; 460 return false;
430 } 461 }
431 return DeleteRecursively(&path); 462 return DeleteRecursively(&path);
432 } 463 }
433 } 464 }
434 465
435 466
436 bool Directory::Rename(const char* path, const char* new_path) { 467 bool Directory::Rename(const char* path, const char* new_path) {
437 ExistsResult exists = Exists(path); 468 ExistsResult exists = Exists(path);
438 if (exists != EXISTS) return false; 469 if (exists != EXISTS) {
470 return false;
471 }
439 return NO_RETRY_EXPECTED(rename(path, new_path)) == 0; 472 return NO_RETRY_EXPECTED(rename(path, new_path)) == 0;
440 } 473 }
441 474
442 } // namespace bin 475 } // namespace bin
443 } // namespace dart 476 } // namespace dart
444 477
445 #endif // defined(TARGET_OS_LINUX) 478 #endif // defined(TARGET_OS_LINUX)
OLDNEW
« no previous file with comments | « runtime/bin/directory_android.cc ('k') | runtime/bin/directory_macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698