| 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 "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> |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 path_length, | 143 path_length, |
| 144 recursive, | 144 recursive, |
| 145 listing); | 145 listing); |
| 146 break; | 146 break; |
| 147 case DT_REG: | 147 case DT_REG: |
| 148 success = success && HandleFile(entry.d_name, | 148 success = success && HandleFile(entry.d_name, |
| 149 path, | 149 path, |
| 150 path_length, | 150 path_length, |
| 151 listing); | 151 listing); |
| 152 break; | 152 break; |
| 153 case DT_LNK: |
| 153 case DT_UNKNOWN: { | 154 case DT_UNKNOWN: { |
| 154 // On some file systems the entry type is not determined by | 155 // On some file systems the entry type is not determined by |
| 155 // readdir_r. For those we use lstat to determine the entry | 156 // readdir_r. For those and for links we use stat to determine |
| 156 // type. | 157 // the actual entry type. Notice that stat returns the type of |
| 158 // the file pointed to. |
| 157 struct stat entry_info; | 159 struct stat entry_info; |
| 158 size_t written = snprintf(path + path_length, | 160 size_t written = snprintf(path + path_length, |
| 159 PATH_MAX - path_length, | 161 PATH_MAX - path_length, |
| 160 "%s", | 162 "%s", |
| 161 entry.d_name); | 163 entry.d_name); |
| 162 if (written != strlen(entry.d_name)) { | 164 if (written != strlen(entry.d_name)) { |
| 163 success = false; | 165 success = false; |
| 164 break; | 166 break; |
| 165 } | 167 } |
| 166 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info)); | 168 int stat_success = TEMP_FAILURE_RETRY(stat(path, &entry_info)); |
| 167 if (lstat_success == -1) { | 169 if (stat_success == -1) { |
| 168 success = false; | 170 success = false; |
| 169 PostError(listing, path); | 171 PostError(listing, path); |
| 170 break; | 172 break; |
| 171 } | 173 } |
| 172 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { | 174 if (S_ISDIR(entry_info.st_mode)) { |
| 173 success = success && HandleDir(entry.d_name, | 175 success = success && HandleDir(entry.d_name, |
| 174 path, | 176 path, |
| 175 path_length, | 177 path_length, |
| 176 recursive, | 178 recursive, |
| 177 listing); | 179 listing); |
| 178 } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) { | 180 } else if (S_ISREG(entry_info.st_mode)) { |
| 179 success = success && HandleFile(entry.d_name, | 181 success = success && HandleFile(entry.d_name, |
| 180 path, | 182 path, |
| 181 path_length, | 183 path_length, |
| 182 listing); | 184 listing); |
| 183 } | 185 } |
| 186 ASSERT(!S_ISLNK(entry_info.st_mode)); |
| 184 break; | 187 break; |
| 185 } | 188 } |
| 186 default: | 189 default: |
| 187 break; | 190 break; |
| 188 } | 191 } |
| 189 } | 192 } |
| 190 | 193 |
| 191 if (read != 0) { | 194 if (read != 0) { |
| 192 errno = read; | 195 errno = read; |
| 193 success = false; | 196 success = false; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 if (written != strlen(dir_name)) { | 233 if (written != strlen(dir_name)) { |
| 231 return false; | 234 return false; |
| 232 } | 235 } |
| 233 return DeleteRecursively(path); | 236 return DeleteRecursively(path); |
| 234 } | 237 } |
| 235 return true; | 238 return true; |
| 236 } | 239 } |
| 237 | 240 |
| 238 | 241 |
| 239 static bool DeleteRecursively(const char* dir_name) { | 242 static bool DeleteRecursively(const char* dir_name) { |
| 243 // Do not recurse into links for deletion. Instead delete the link. |
| 244 struct stat st; |
| 245 if (TEMP_FAILURE_RETRY(lstat(dir_name, &st)) == -1) { |
| 246 return false; |
| 247 } else if (S_ISLNK(st.st_mode)) { |
| 248 return (remove(dir_name) == 0); |
| 249 } |
| 250 |
| 251 // Not a link. Attempt to open as a directory and recurse into the |
| 252 // directory. |
| 240 DIR* dir_pointer; | 253 DIR* dir_pointer; |
| 241 do { | 254 do { |
| 242 dir_pointer = opendir(dir_name); | 255 dir_pointer = opendir(dir_name); |
| 243 } while (dir_pointer == NULL && errno == EINTR); | 256 } while (dir_pointer == NULL && errno == EINTR); |
| 244 | 257 |
| 245 if (dir_pointer == NULL) { | 258 if (dir_pointer == NULL) { |
| 246 return false; | 259 return false; |
| 247 } | 260 } |
| 248 | 261 |
| 249 // Compute full path for the directory currently being deleted. The | 262 // Compute full path for the directory currently being deleted. The |
| (...skipping 18 matching lines...) Expand all Loading... |
| 268 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, | 281 while ((read = TEMP_FAILURE_RETRY(readdir_r(dir_pointer, |
| 269 &entry, | 282 &entry, |
| 270 &result))) == 0 && | 283 &result))) == 0 && |
| 271 result != NULL && | 284 result != NULL && |
| 272 success) { | 285 success) { |
| 273 switch (entry.d_type) { | 286 switch (entry.d_type) { |
| 274 case DT_DIR: | 287 case DT_DIR: |
| 275 success = success && DeleteDir(entry.d_name, path, path_length); | 288 success = success && DeleteDir(entry.d_name, path, path_length); |
| 276 break; | 289 break; |
| 277 case DT_REG: | 290 case DT_REG: |
| 291 case DT_LNK: |
| 292 // Treat all links as files. This will delete the link which |
| 293 // is what we want no matter if the link target is a file or a |
| 294 // directory. |
| 278 success = success && DeleteFile(entry.d_name, path, path_length); | 295 success = success && DeleteFile(entry.d_name, path, path_length); |
| 279 break; | 296 break; |
| 280 case DT_UNKNOWN: { | 297 case DT_UNKNOWN: { |
| 281 // On some file systems the entry type is not determined by | 298 // On some file systems the entry type is not determined by |
| 282 // readdir_r. For those we use lstat to determine the entry | 299 // readdir_r. For those we use lstat to determine the entry |
| 283 // type. | 300 // type. |
| 284 struct stat entry_info; | 301 struct stat entry_info; |
| 285 size_t written = snprintf(path + path_length, | 302 size_t written = snprintf(path + path_length, |
| 286 PATH_MAX - path_length, | 303 PATH_MAX - path_length, |
| 287 "%s", | 304 "%s", |
| 288 entry.d_name); | 305 entry.d_name); |
| 289 if (written != strlen(entry.d_name)) { | 306 if (written != strlen(entry.d_name)) { |
| 290 success = false; | 307 success = false; |
| 291 break; | 308 break; |
| 292 } | 309 } |
| 293 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info)); | 310 int lstat_success = TEMP_FAILURE_RETRY(lstat(path, &entry_info)); |
| 294 if (lstat_success == -1) { | 311 if (lstat_success == -1) { |
| 295 success = false; | 312 success = false; |
| 296 break; | 313 break; |
| 297 } | 314 } |
| 298 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { | 315 if (S_ISDIR(entry_info.st_mode)) { |
| 299 success = success && DeleteDir(entry.d_name, path, path_length); | 316 success = success && DeleteDir(entry.d_name, path, path_length); |
| 300 } else if ((entry_info.st_mode & S_IFMT) == S_IFREG) { | 317 } else if (S_ISREG(entry_info.st_mode) || S_ISLNK(entry_info.st_mode)) { |
| 318 // Treat links as files. This will delete the link which is |
| 319 // what we want no matter if the link target is a file or a |
| 320 // directory. |
| 301 success = success && DeleteFile(entry.d_name, path, path_length); | 321 success = success && DeleteFile(entry.d_name, path, path_length); |
| 302 } | 322 } |
| 303 break; | 323 break; |
| 304 } | 324 } |
| 305 default: | 325 default: |
| 306 break; | 326 break; |
| 307 } | 327 } |
| 308 } | 328 } |
| 309 | 329 |
| 310 free(path); | 330 free(path); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 322 bool Directory::List(const char* dir_name, | 342 bool Directory::List(const char* dir_name, |
| 323 bool recursive, | 343 bool recursive, |
| 324 DirectoryListing *listing) { | 344 DirectoryListing *listing) { |
| 325 bool completed = ListRecursively(dir_name, recursive, listing); | 345 bool completed = ListRecursively(dir_name, recursive, listing); |
| 326 return completed; | 346 return completed; |
| 327 } | 347 } |
| 328 | 348 |
| 329 | 349 |
| 330 Directory::ExistsResult Directory::Exists(const char* dir_name) { | 350 Directory::ExistsResult Directory::Exists(const char* dir_name) { |
| 331 struct stat entry_info; | 351 struct stat entry_info; |
| 332 int lstat_success = TEMP_FAILURE_RETRY(lstat(dir_name, &entry_info)); | 352 int success = TEMP_FAILURE_RETRY(stat(dir_name, &entry_info)); |
| 333 if (lstat_success == 0) { | 353 if (success == 0) { |
| 334 if ((entry_info.st_mode & S_IFMT) == S_IFDIR) { | 354 if (S_ISDIR(entry_info.st_mode)) { |
| 335 return EXISTS; | 355 return EXISTS; |
| 336 } else { | 356 } else { |
| 337 return DOES_NOT_EXIST; | 357 return DOES_NOT_EXIST; |
| 338 } | 358 } |
| 339 } else { | 359 } else { |
| 340 if (errno == EACCES || | 360 if (errno == EACCES || |
| 341 errno == EBADF || | 361 errno == EBADF || |
| 342 errno == EFAULT || | 362 errno == EFAULT || |
| 343 errno == ENOMEM || | 363 errno == ENOMEM || |
| 344 errno == EOVERFLOW) { | 364 errno == EOVERFLOW) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 } | 417 } |
| 398 | 418 |
| 399 | 419 |
| 400 bool Directory::Delete(const char* dir_name, bool recursive) { | 420 bool Directory::Delete(const char* dir_name, bool recursive) { |
| 401 if (!recursive) { | 421 if (!recursive) { |
| 402 return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0); | 422 return (TEMP_FAILURE_RETRY(remove(dir_name)) == 0); |
| 403 } else { | 423 } else { |
| 404 return DeleteRecursively(dir_name); | 424 return DeleteRecursively(dir_name); |
| 405 } | 425 } |
| 406 } | 426 } |
| OLD | NEW |