(stack, isbytes, topdown, onerror, follow_symlinks)
| 502 | _fwalk_close = 2 # args: dirfd |
| 503 | |
| 504 | def _fwalk(stack, isbytes, topdown, onerror, follow_symlinks): |
| 505 | # Note: This uses O(depth of the directory tree) file descriptors: if |
| 506 | # necessary, it can be adapted to only require O(1) FDs, see issue |
| 507 | # #13734. |
| 508 | |
| 509 | action, value = stack.pop() |
| 510 | if action == _fwalk_close: |
| 511 | close(value) |
| 512 | return |
| 513 | elif action == _fwalk_yield: |
| 514 | yield value |
| 515 | return |
| 516 | assert action == _fwalk_walk |
| 517 | isroot, dirfd, toppath, topname, entry = value |
| 518 | try: |
| 519 | if not follow_symlinks: |
| 520 | # Note: To guard against symlink races, we use the standard |
| 521 | # lstat()/open()/fstat() trick. |
| 522 | if entry is None: |
| 523 | orig_st = stat(topname, follow_symlinks=False, dir_fd=dirfd) |
| 524 | else: |
| 525 | orig_st = entry.stat(follow_symlinks=False) |
| 526 | topfd = open(topname, O_RDONLY | O_NONBLOCK, dir_fd=dirfd) |
| 527 | except OSError as err: |
| 528 | if isroot: |
| 529 | raise |
| 530 | if onerror is not None: |
| 531 | onerror(err) |
| 532 | return |
| 533 | stack.append((_fwalk_close, topfd)) |
| 534 | if not follow_symlinks: |
| 535 | if isroot and not st.S_ISDIR(orig_st.st_mode): |
| 536 | return |
| 537 | if not path.samestat(orig_st, stat(topfd)): |
| 538 | return |
| 539 | |
| 540 | scandir_it = scandir(topfd) |
| 541 | dirs = [] |
| 542 | nondirs = [] |
| 543 | entries = None if topdown or follow_symlinks else [] |
| 544 | for entry in scandir_it: |
| 545 | name = entry.name |
| 546 | if isbytes: |
| 547 | name = fsencode(name) |
| 548 | try: |
| 549 | if entry.is_dir(): |
| 550 | dirs.append(name) |
| 551 | if entries is not None: |
| 552 | entries.append(entry) |
| 553 | else: |
| 554 | nondirs.append(name) |
| 555 | except OSError: |
| 556 | try: |
| 557 | # Add dangling symlinks, ignore disappeared files |
| 558 | if entry.is_symlink(): |
| 559 | nondirs.append(name) |
| 560 | except OSError: |
| 561 | pass |
no test coverage detected
searching dependent graphs…