OLD | NEW |
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 <string.h> // NOLINT | 12 #include <string.h> // NOLINT |
13 #include <sys/param.h> // NOLINT | 13 #include <sys/param.h> // NOLINT |
14 #include <sys/stat.h> // NOLINT | 14 #include <sys/stat.h> // NOLINT |
15 #include <unistd.h> // NOLINT | 15 #include <unistd.h> // NOLINT |
16 | 16 |
17 #include "bin/file.h" | 17 #include "bin/file.h" |
18 #include "bin/platform.h" | 18 #include "bin/platform.h" |
19 | 19 |
20 | 20 |
21 namespace dart { | 21 namespace dart { |
22 namespace bin { | 22 namespace bin { |
23 | 23 |
24 class PathBuffer { | 24 |
25 public: | 25 PathBuffer::PathBuffer() : length_(0) { |
26 PathBuffer() : length(0) { | 26 data_ = new char[PATH_MAX + 1]; |
27 data = new char[PATH_MAX + 1]; | 27 } |
| 28 |
| 29 bool PathBuffer::AddW(const wchar_t* name) { |
| 30 UNREACHABLE(); |
| 31 return false; |
| 32 } |
| 33 |
| 34 char* PathBuffer::AsString() const { |
| 35 return reinterpret_cast<char*>(data_); |
| 36 } |
| 37 |
| 38 wchar_t* PathBuffer::AsStringW() const { |
| 39 UNREACHABLE(); |
| 40 return NULL; |
| 41 } |
| 42 |
| 43 bool PathBuffer::Add(const char* name) { |
| 44 char* data = AsString(); |
| 45 int written = snprintf(data + length_, |
| 46 PATH_MAX - length_, |
| 47 "%s", |
| 48 name); |
| 49 data[PATH_MAX] = '\0'; |
| 50 if (written <= PATH_MAX - length_ && |
| 51 written >= 0 && |
| 52 static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1)) { |
| 53 length_ += written; |
| 54 return true; |
| 55 } else { |
| 56 errno = ENAMETOOLONG; |
| 57 return false; |
28 } | 58 } |
| 59 } |
29 | 60 |
30 ~PathBuffer() { | 61 void PathBuffer::Reset(int new_length) { |
31 delete[] data; | 62 length_ = new_length; |
32 } | 63 AsString()[length_] = '\0'; |
33 | 64 } |
34 char* data; | |
35 int length; | |
36 | |
37 bool Add(const char* name) { | |
38 int written = snprintf(data + length, | |
39 PATH_MAX - length, | |
40 "%s", | |
41 name); | |
42 data[PATH_MAX] = '\0'; | |
43 if (written <= PATH_MAX - length && | |
44 written >= 0 && | |
45 static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1)) { | |
46 length += written; | |
47 return true; | |
48 } else { | |
49 errno = ENAMETOOLONG; | |
50 return false; | |
51 } | |
52 } | |
53 | |
54 void Reset(int new_length) { | |
55 length = new_length; | |
56 data[length] = '\0'; | |
57 } | |
58 }; | |
59 | 65 |
60 | 66 |
61 // A linked list of symbolic links, with their unique file system identifiers. | 67 // A linked list of symbolic links, with their unique file system identifiers. |
62 // These are scanned to detect loops while doing a recursive directory listing. | 68 // These are scanned to detect loops while doing a recursive directory listing. |
63 struct LinkList { | 69 struct LinkList { |
64 dev_t dev; | 70 dev_t dev; |
65 ino_t ino; | 71 ino_t ino; |
66 LinkList* next; | 72 LinkList* next; |
67 }; | 73 }; |
68 | 74 |
69 | 75 |
70 // Forward declarations. | 76 ListType DirectoryListingEntry::Next(DirectoryListing* listing) { |
71 static bool ListRecursively(PathBuffer* path, | 77 if (done_) { |
72 bool recursive, | 78 return kListDone; |
73 bool follow_links, | 79 } |
74 LinkList* seen, | |
75 DirectoryListing* listing); | |
76 static bool DeleteRecursively(PathBuffer* path); | |
77 | 80 |
| 81 if (lister_ == 0) { |
| 82 if (!listing->path_buffer().Add(File::PathSeparator())) { |
| 83 done_ = true; |
| 84 return kListError; |
| 85 } |
| 86 path_length_ = listing->path_buffer().length(); |
| 87 do { |
| 88 lister_ = reinterpret_cast<intptr_t>( |
| 89 opendir(listing->path_buffer().AsString())); |
| 90 } while (lister_ == 0 && errno == EINTR); |
78 | 91 |
79 static void PostError(DirectoryListing *listing, | 92 if (lister_ == 0) { |
80 const char* dir_name) { | 93 done_ = true; |
81 listing->HandleError(dir_name); | 94 return kListError; |
82 } | 95 } |
83 | |
84 | |
85 static bool HandleDir(char* dir_name, | |
86 PathBuffer* path, | |
87 bool recursive, | |
88 bool follow_links, | |
89 LinkList* seen, | |
90 DirectoryListing *listing) { | |
91 if (strcmp(dir_name, ".") == 0) return true; | |
92 if (strcmp(dir_name, "..") == 0) return true; | |
93 if (!path->Add(dir_name)) { | |
94 PostError(listing, path->data); | |
95 return false; | |
96 } | 96 } |
97 return listing->HandleDirectory(path->data) && | 97 // Reset. |
98 (!recursive || | 98 listing->path_buffer().Reset(path_length_); |
99 ListRecursively(path, recursive, follow_links, seen, listing)); | 99 ResetLink(); |
100 } | |
101 | |
102 | |
103 static bool HandleFile(char* file_name, | |
104 PathBuffer* path, | |
105 DirectoryListing *listing) { | |
106 if (!path->Add(file_name)) { | |
107 PostError(listing, path->data); | |
108 return false; | |
109 } | |
110 return listing->HandleFile(path->data); | |
111 } | |
112 | |
113 | |
114 static bool HandleLink(char* link_name, | |
115 PathBuffer* path, | |
116 DirectoryListing *listing) { | |
117 if (!path->Add(link_name)) { | |
118 PostError(listing, path->data); | |
119 return false; | |
120 } | |
121 return listing->HandleLink(path->data); | |
122 } | |
123 | |
124 | |
125 static bool ListRecursively(PathBuffer* path, | |
126 bool recursive, | |
127 bool follow_links, | |
128 LinkList* seen, | |
129 DirectoryListing *listing) { | |
130 if (!path->Add(File::PathSeparator())) { | |
131 PostError(listing, path->data); | |
132 return false; | |
133 } | |
134 DIR* dir_pointer; | |
135 do { | |
136 dir_pointer = opendir(path->data); | |
137 } while (dir_pointer == NULL && errno == EINTR); | |
138 if (dir_pointer == NULL) { | |
139 PostError(listing, path->data); | |
140 return false; | |
141 } | |
142 | 100 |
143 // Iterate the directory and post the directories and files to the | 101 // Iterate the directory and post the directories and files to the |
144 // ports. | 102 // ports. |
145 int path_length = path->length; | |
146 int status = 0; | 103 int status = 0; |
147 bool success = true; | |
148 dirent entry; | 104 dirent entry; |
149 dirent* result; | 105 dirent* result; |
150 while ((status = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, | 106 if ((status = TEMP_FAILURE_RETRY(readdir_r(reinterpret_cast<DIR*>(lister_), |
151 &entry, | 107 &entry, |
152 &result))) == 0 && | 108 &result))) == 0 && |
153 result != NULL) { | 109 result != NULL) { |
| 110 if (!listing->path_buffer().Add(entry.d_name)) { |
| 111 done_ = true; |
| 112 return kListError; |
| 113 } |
154 switch (entry.d_type) { | 114 switch (entry.d_type) { |
155 case DT_DIR: | 115 case DT_DIR: |
156 success = HandleDir(entry.d_name, | 116 if (strcmp(entry.d_name, ".") == 0) return Next(listing); |
157 path, | 117 if (strcmp(entry.d_name, "..") == 0) return Next(listing); |
158 recursive, | 118 return kListDirectory; |
159 follow_links, | |
160 seen, | |
161 listing) && success; | |
162 break; | |
163 case DT_REG: | 119 case DT_REG: |
164 success = HandleFile(entry.d_name, | 120 return kListFile; |
165 path, | |
166 listing) && success; | |
167 break; | |
168 case DT_LNK: | 121 case DT_LNK: |
169 if (!follow_links) { | 122 if (!listing->follow_links()) { |
170 success = HandleLink(entry.d_name, | 123 return kListLink; |
171 path, | |
172 listing) && success; | |
173 break; | |
174 } | 124 } |
175 // Else fall through to next case. | 125 // Else fall through to next case. |
176 // Fall through. | 126 // Fall through. |
177 case DT_UNKNOWN: { | 127 case DT_UNKNOWN: { |
178 // On some file systems the entry type is not determined by | 128 // On some file systems the entry type is not determined by |
179 // readdir_r. For those and for links we use stat to determine | 129 // readdir_r. For those and for links we use stat to determine |
180 // the actual entry type. Notice that stat returns the type of | 130 // the actual entry type. Notice that stat returns the type of |
181 // the file pointed to. | 131 // the file pointed to. |
182 struct stat entry_info; | 132 struct stat entry_info; |
183 if (!path->Add(entry.d_name)) { | 133 int stat_success; |
184 success = false; | 134 stat_success = TEMP_FAILURE_RETRY( |
185 break; | 135 lstat(listing->path_buffer().AsString(), &entry_info)); |
| 136 if (stat_success == -1) { |
| 137 return kListError; |
186 } | 138 } |
187 int stat_success; | 139 if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) { |
188 stat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info)); | |
189 if (stat_success == -1) { | |
190 success = false; | |
191 PostError(listing, path->data); | |
192 break; | |
193 } | |
194 if (follow_links && S_ISLNK(entry_info.st_mode)) { | |
195 // Check to see if we are in a loop created by a symbolic link. | 140 // Check to see if we are in a loop created by a symbolic link. |
196 LinkList current_link = { entry_info.st_dev, | 141 LinkList current_link = { entry_info.st_dev, |
197 entry_info.st_ino, | 142 entry_info.st_ino, |
198 seen }; | 143 link_ }; |
199 LinkList* previous = seen; | 144 LinkList* previous = link_; |
200 bool looping_link = false; | |
201 while (previous != NULL) { | 145 while (previous != NULL) { |
202 if (previous->dev == current_link.dev && | 146 if (previous->dev == current_link.dev && |
203 previous->ino == current_link.ino) { | 147 previous->ino == current_link.ino) { |
204 // Report the looping link as a link, rather than following it. | 148 // Report the looping link as a link, rather than following it. |
205 path->Reset(path_length); | 149 return kListLink; |
206 success = HandleLink(entry.d_name, | |
207 path, | |
208 listing) && success; | |
209 looping_link = true; | |
210 break; | |
211 } | 150 } |
212 previous = previous->next; | 151 previous = previous->next; |
213 } | 152 } |
214 if (looping_link) break; | 153 stat_success = TEMP_FAILURE_RETRY( |
215 stat_success = TEMP_FAILURE_RETRY(stat(path->data, &entry_info)); | 154 stat(listing->path_buffer().AsString(), &entry_info)); |
216 if (stat_success == -1) { | 155 if (stat_success == -1) { |
217 // Report a broken link as a link, even if follow_links is true. | 156 // Report a broken link as a link, even if follow_links is true. |
218 path->Reset(path_length); | 157 return kListLink; |
219 success = HandleLink(entry.d_name, | |
220 path, | |
221 listing) && success; | |
222 break; | |
223 } | 158 } |
224 if (S_ISDIR(entry_info.st_mode)) { | 159 if (S_ISDIR(entry_info.st_mode)) { |
225 // Recurse into the subdirectory with current_link added to the | 160 // Recurse into the subdirectory with current_link added to the |
226 // linked list of seen file system links. | 161 // linked list of seen file system links. |
227 path->Reset(path_length); | 162 link_ = new LinkList(current_link); |
228 success = HandleDir(entry.d_name, | 163 if (strcmp(entry.d_name, ".") == 0) return Next(listing); |
229 path, | 164 if (strcmp(entry.d_name, "..") == 0) return Next(listing); |
230 recursive, | 165 return kListDirectory; |
231 follow_links, | |
232 ¤t_link, | |
233 listing) && success; | |
234 break; | |
235 } | 166 } |
236 } | 167 } |
237 path->Reset(path_length); | |
238 if (S_ISDIR(entry_info.st_mode)) { | 168 if (S_ISDIR(entry_info.st_mode)) { |
239 success = HandleDir(entry.d_name, | 169 if (strcmp(entry.d_name, ".") == 0) return Next(listing); |
240 path, | 170 if (strcmp(entry.d_name, "..") == 0) return Next(listing); |
241 recursive, | 171 return kListDirectory; |
242 follow_links, | |
243 seen, | |
244 listing) && success; | |
245 } else if (S_ISREG(entry_info.st_mode)) { | 172 } else if (S_ISREG(entry_info.st_mode)) { |
246 success = HandleFile(entry.d_name, | 173 return kListFile; |
247 path, | |
248 listing) && success; | |
249 } else if (S_ISLNK(entry_info.st_mode)) { | 174 } else if (S_ISLNK(entry_info.st_mode)) { |
250 success = HandleLink(entry.d_name, | 175 return kListLink; |
251 path, | |
252 listing) && success; | |
253 } | 176 } |
254 break; | |
255 } | 177 } |
| 178 |
256 default: | 179 default: |
257 break; | 180 break; |
258 } | 181 } |
259 path->Reset(path_length); | |
260 } | 182 } |
| 183 done_ = true; |
261 | 184 |
262 if (status != 0) { | 185 if (status != 0) { |
263 errno = status; | 186 errno = status; |
264 success = false; | 187 return kListError; |
265 PostError(listing, path->data); | |
266 } | 188 } |
267 | 189 |
268 if (closedir(dir_pointer) == -1) { | 190 if (closedir(reinterpret_cast<DIR*>(lister_)) == -1) { |
269 success = false; | 191 return kListError; |
270 PostError(listing, path->data); | |
271 } | 192 } |
272 | 193 |
273 return success; | 194 return kListDone; |
274 } | 195 } |
275 | 196 |
276 | 197 |
| 198 static bool DeleteRecursively(PathBuffer* path); |
| 199 |
| 200 |
277 static bool DeleteFile(char* file_name, | 201 static bool DeleteFile(char* file_name, |
278 PathBuffer* path) { | 202 PathBuffer* path) { |
279 return path->Add(file_name) && unlink(path->data) == 0; | 203 return path->Add(file_name) && unlink(path->AsString()) == 0; |
280 } | 204 } |
281 | 205 |
282 | 206 |
283 static bool DeleteDir(char* dir_name, | 207 static bool DeleteDir(char* dir_name, |
284 PathBuffer* path) { | 208 PathBuffer* path) { |
285 if (strcmp(dir_name, ".") == 0) return true; | 209 if (strcmp(dir_name, ".") == 0) return true; |
286 if (strcmp(dir_name, "..") == 0) return true; | 210 if (strcmp(dir_name, "..") == 0) return true; |
287 return path->Add(dir_name) && DeleteRecursively(path); | 211 return path->Add(dir_name) && DeleteRecursively(path); |
288 } | 212 } |
289 | 213 |
290 | 214 |
291 static bool DeleteRecursively(PathBuffer* path) { | 215 static bool DeleteRecursively(PathBuffer* path) { |
292 // Do not recurse into links for deletion. Instead delete the link. | 216 // Do not recurse into links for deletion. Instead delete the link. |
293 // If it's a file, delete it. | 217 // If it's a file, delete it. |
294 struct stat st; | 218 struct stat st; |
295 if (TEMP_FAILURE_RETRY(lstat(path->data, &st)) == -1) { | 219 if (TEMP_FAILURE_RETRY(lstat(path->AsString(), &st)) == -1) { |
296 return false; | 220 return false; |
297 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { | 221 } else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { |
298 return (unlink(path->data) == 0); | 222 return (unlink(path->AsString()) == 0); |
299 } | 223 } |
300 | 224 |
301 if (!path->Add(File::PathSeparator())) return false; | 225 if (!path->Add(File::PathSeparator())) return false; |
302 | 226 |
303 // Not a link. Attempt to open as a directory and recurse into the | 227 // Not a link. Attempt to open as a directory and recurse into the |
304 // directory. | 228 // directory. |
305 DIR* dir_pointer; | 229 DIR* dir_pointer; |
306 do { | 230 do { |
307 dir_pointer = opendir(path->data); | 231 dir_pointer = opendir(path->AsString()); |
308 } while (dir_pointer == NULL && errno == EINTR); | 232 } while (dir_pointer == NULL && errno == EINTR); |
309 | 233 |
310 if (dir_pointer == NULL) { | 234 if (dir_pointer == NULL) { |
311 return false; | 235 return false; |
312 } | 236 } |
313 | 237 |
314 // Iterate the directory and delete all files and directories. | 238 // Iterate the directory and delete all files and directories. |
315 int path_length = path->length; | 239 int path_length = path->length(); |
316 int read = 0; | 240 int read = 0; |
317 bool success = true; | 241 bool success = true; |
318 dirent entry; | 242 dirent entry; |
319 dirent* result; | 243 dirent* result; |
320 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, | 244 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, |
321 &entry, | 245 &entry, |
322 &result))) == 0 && | 246 &result))) == 0 && |
323 result != NULL && | 247 result != NULL && |
324 success) { | 248 success) { |
325 switch (entry.d_type) { | 249 switch (entry.d_type) { |
326 case DT_DIR: | 250 case DT_DIR: |
327 success = success && DeleteDir(entry.d_name, path); | 251 success = success && DeleteDir(entry.d_name, path); |
328 break; | 252 break; |
329 case DT_REG: | 253 case DT_REG: |
330 case DT_LNK: | 254 case DT_LNK: |
331 // Treat all links as files. This will delete the link which | 255 // Treat all links as files. This will delete the link which |
332 // is what we want no matter if the link target is a file or a | 256 // is what we want no matter if the link target is a file or a |
333 // directory. | 257 // directory. |
334 success = success && DeleteFile(entry.d_name, path); | 258 success = success && DeleteFile(entry.d_name, path); |
335 break; | 259 break; |
336 case DT_UNKNOWN: { | 260 case DT_UNKNOWN: { |
337 // On some file systems the entry type is not determined by | 261 // On some file systems the entry type is not determined by |
338 // readdir_r. For those we use lstat to determine the entry | 262 // readdir_r. For those we use lstat to determine the entry |
339 // type. | 263 // type. |
340 struct stat entry_info; | 264 struct stat entry_info; |
341 if (!path->Add(entry.d_name)) { | 265 if (!path->Add(entry.d_name)) { |
342 success = false; | 266 success = false; |
343 break; | 267 break; |
344 } | 268 } |
345 int lstat_success = TEMP_FAILURE_RETRY(lstat(path->data, &entry_info)); | 269 int lstat_success = TEMP_FAILURE_RETRY( |
| 270 lstat(path->AsString(), &entry_info)); |
346 if (lstat_success == -1) { | 271 if (lstat_success == -1) { |
347 success = false; | 272 success = false; |
348 break; | 273 break; |
349 } | 274 } |
350 path->Reset(path_length); | 275 path->Reset(path_length); |
351 if (S_ISDIR(entry_info.st_mode)) { | 276 if (S_ISDIR(entry_info.st_mode)) { |
352 success = success && DeleteDir(entry.d_name, path); | 277 success = success && DeleteDir(entry.d_name, path); |
353 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { | 278 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { |
354 // Treat links as files. This will delete the link which is | 279 // Treat links as files. This will delete the link which is |
355 // what we want no matter if the link target is a file or a | 280 // what we want no matter if the link target is a file or a |
356 // directory. | 281 // directory. |
357 success = success && DeleteFile(entry.d_name, path); | 282 success = success && DeleteFile(entry.d_name, path); |
358 } | 283 } |
359 break; | 284 break; |
360 } | 285 } |
361 default: | 286 default: |
362 break; | 287 break; |
363 } | 288 } |
364 path->Reset(path_length); | 289 path->Reset(path_length); |
365 } | 290 } |
366 | 291 |
367 if ((read != 0) || | 292 if ((read != 0) || |
368 (closedir(dir_pointer) == -1) || | 293 (closedir(dir_pointer) == -1) || |
369 (remove(path->data) == -1)) { | 294 (remove(path->AsString()) == -1)) { |
370 return false; | 295 return false; |
371 } | 296 } |
372 return success; | 297 return success; |
373 } | 298 } |
374 | 299 |
375 | 300 |
376 bool Directory::List(const char* dir_name, | |
377 bool recursive, | |
378 bool follow_links, | |
379 DirectoryListing *listing) { | |
380 PathBuffer path; | |
381 if (!path.Add(dir_name)) { | |
382 PostError(listing, dir_name); | |
383 return false; | |
384 } | |
385 return ListRecursively(&path, recursive, follow_links, NULL, listing); | |
386 } | |
387 | |
388 | |
389 Directory::ExistsResult Directory::Exists(const char* dir_name) { | 301 Directory::ExistsResult Directory::Exists(const char* dir_name) { |
390 struct stat entry_info; | 302 struct stat entry_info; |
391 int success = TEMP_FAILURE_RETRY(stat(dir_name, &entry_info)); | 303 int success = TEMP_FAILURE_RETRY(stat(dir_name, &entry_info)); |
392 if (success == 0) { | 304 if (success == 0) { |
393 if (S_ISDIR(entry_info.st_mode)) { | 305 if (S_ISDIR(entry_info.st_mode)) { |
394 return EXISTS; | 306 return EXISTS; |
395 } else { | 307 } else { |
396 return DOES_NOT_EXIST; | 308 return DOES_NOT_EXIST; |
397 } | 309 } |
398 } else { | 310 } else { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 } | 361 } |
450 | 362 |
451 | 363 |
452 char* Directory::CreateTemp(const char* const_template) { | 364 char* Directory::CreateTemp(const char* const_template) { |
453 // Returns a new, unused directory name, modifying the contents of | 365 // Returns a new, unused directory name, modifying the contents of |
454 // dir_template. Creates the directory with the permissions specified | 366 // dir_template. Creates the directory with the permissions specified |
455 // by the process umask. | 367 // by the process umask. |
456 // The return value must be freed by the caller. | 368 // The return value must be freed by the caller. |
457 PathBuffer path; | 369 PathBuffer path; |
458 path.Add(const_template); | 370 path.Add(const_template); |
459 if (path.length == 0) { | 371 if (path.length() == 0) { |
460 path.Add("/tmp/temp_dir1_"); | 372 path.Add("/tmp/temp_dir1_"); |
461 } else if ((path.data)[path.length - 1] == '/') { | 373 } else if ((path.AsString())[path.length() - 1] == '/') { |
462 path.Add("temp_dir_"); | 374 path.Add("temp_dir_"); |
463 } | 375 } |
464 if (!path.Add("XXXXXX")) { | 376 if (!path.Add("XXXXXX")) { |
465 // Pattern has overflowed. | 377 // Pattern has overflowed. |
466 return NULL; | 378 return NULL; |
467 } | 379 } |
468 char* result; | 380 char* result; |
469 do { | 381 do { |
470 result = mkdtemp(path.data); | 382 result = mkdtemp(path.AsString()); |
471 } while (result == NULL && errno == EINTR); | 383 } while (result == NULL && errno == EINTR); |
472 if (result == NULL) { | 384 if (result == NULL) { |
473 return NULL; | 385 return NULL; |
474 } | 386 } |
475 int length = strnlen(path.data, PATH_MAX); | 387 int length = strnlen(path.AsString(), PATH_MAX); |
476 result = static_cast<char*>(malloc(length + 1)); | 388 result = static_cast<char*>(malloc(length + 1)); |
477 strncpy(result, path.data, length); | 389 strncpy(result, path.AsString(), length); |
478 result[length] = '\0'; | 390 result[length] = '\0'; |
479 return result; | 391 return result; |
480 } | 392 } |
481 | 393 |
482 | 394 |
483 bool Directory::Delete(const char* dir_name, bool recursive) { | 395 bool Directory::Delete(const char* dir_name, bool recursive) { |
484 if (!recursive) { | 396 if (!recursive) { |
485 if (File::GetType(dir_name, false) == File::kIsLink && | 397 if (File::GetType(dir_name, false) == File::kIsLink && |
486 File::GetType(dir_name, true) == File::kIsDirectory) { | 398 File::GetType(dir_name, true) == File::kIsDirectory) { |
487 return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0); | 399 return (TEMP_FAILURE_RETRY(unlink(dir_name)) == 0); |
(...skipping 12 matching lines...) Expand all Loading... |
500 bool Directory::Rename(const char* path, const char* new_path) { | 412 bool Directory::Rename(const char* path, const char* new_path) { |
501 ExistsResult exists = Exists(path); | 413 ExistsResult exists = Exists(path); |
502 if (exists != EXISTS) return false; | 414 if (exists != EXISTS) return false; |
503 return (TEMP_FAILURE_RETRY(rename(path, new_path)) == 0); | 415 return (TEMP_FAILURE_RETRY(rename(path, new_path)) == 0); |
504 } | 416 } |
505 | 417 |
506 } // namespace bin | 418 } // namespace bin |
507 } // namespace dart | 419 } // namespace dart |
508 | 420 |
509 #endif // defined(TARGET_OS_LINUX) | 421 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |