Skip to content

Commit b80108c

Browse files
committed
modify posix part to use block & break block
1 parent c416e22 commit b80108c

File tree

1 file changed

+62
-76
lines changed

1 file changed

+62
-76
lines changed

lib/pure/os.nim

Lines changed: 62 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,7 +2006,7 @@ type OpenDirStatus* = enum
20062006
type WalkStepKind* = enum
20072007
wsOpenDir, ## attempt to open directory
20082008
wsEntryOk, ## the entry is OK
2009-
wsEntryBad ## usually a dangling symlink on posix, when it's unclear if it
2009+
wsEntryBad ## a broken symlink on posix, where it's unclear if it
20102010
## points to a file or directory
20112011
wsInterrupted ## the directory handle got invalidated during reading
20122012

@@ -2024,7 +2024,7 @@ type WalkStep = ref object
20242024
iterator tryWalkDir*(dir: string; relative=false): WalkStep {.
20252025
tags: [ReadDirEffect], raises: [].} =
20262026
## A version of `walkDir iterator <#walkDir.i,string>`_ with more
2027-
## thorough error checking.
2027+
## thorough error checking. It never raises an exception.
20282028
## Yields *steps* of walking through `dir`, each step contains
20292029
## its path ``path``, OS error code ``code`` and additional tag ``kind``.
20302030
## At first step it yields info ``openStatus`` of opening
@@ -2122,89 +2122,75 @@ iterator tryWalkDir*(dir: string; relative=false): WalkStep {.
21222122
defer:
21232123
if d != nil:
21242124
discard closedir(d)
2125-
while not lastIter:
2126-
yieldAllowed = true
2127-
if not init:
2128-
init = true
2129-
d = opendir(dir)
2130-
if d == nil:
2131-
lastIter = true
2132-
res =
2133-
if errno == ENOENT: sOpenDir(odNotFound, dir)
2134-
elif errno == ENOTDIR: sOpenDir(odNotDir, dir)
2135-
elif errno == EACCES: sOpenDir(odAccessDenied, dir)
2136-
else: sOpenDir(odUnknownError, dir)
2137-
else:
2138-
res = sOpenDir(odOpenOk, dir)
2139-
else:
2140-
errno = 0
2141-
var x = readdir(d)
2142-
if x == nil:
2143-
if errno == 0:
2144-
break # normal end, yielding nothing
2145-
else:
2146-
lastIter = true
2147-
res = sGetError(wsInterrupted, dir)
2148-
else:
2125+
block loop:
2126+
while not lastIter:
2127+
block beforeYield:
2128+
if not init:
2129+
init = true
2130+
d = opendir(dir)
2131+
if d == nil:
2132+
lastIter = true
2133+
res =
2134+
if errno == ENOENT: sOpenDir(odNotFound, dir)
2135+
elif errno == ENOTDIR: sOpenDir(odNotDir, dir)
2136+
elif errno == EACCES: sOpenDir(odAccessDenied, dir)
2137+
else: sOpenDir(odUnknownError, dir)
2138+
else:
2139+
res = sOpenDir(odOpenOk, dir)
2140+
break beforeYield
2141+
errno = 0
2142+
var x = readdir(d)
2143+
if x == nil:
2144+
if errno == 0:
2145+
break loop # normal end, yielding nothing
2146+
else:
2147+
lastIter = true
2148+
res = sGetError(wsInterrupted, dir)
2149+
break beforeYield
21492150
when defined(nimNoArrayToCstringConversion):
21502151
var y = $cstring(addr x.d_name)
21512152
else:
21522153
var y = $x.d_name.cstring
21532154
if y == "." or y == "..":
2154-
yieldAllowed = false
2155-
else:
2156-
var s: Stat
2157-
let path = dir / y
2158-
if not relative:
2159-
y = path
2160-
var k = pcFile
2161-
2162-
var useLstat = false
2163-
when defined(linux) or defined(macosx) or
2164-
defined(bsd) or defined(genode) or defined(nintendoswitch):
2165-
if x.d_type != DT_UNKNOWN:
2166-
if x.d_type == DT_DIR:
2167-
k = pcDir
2168-
res = sNoErrors(k, y)
2169-
elif x.d_type == DT_LNK:
2170-
errno = 0
2171-
if dirExists(path): k = pcLinkToDir
2172-
else: k = pcLinkToFile
2173-
if errno == 0: # check error in dirExists
2174-
res = sNoErrors(k, y)
2175-
else:
2176-
res = sGetError(wsEntryBad, y)
2177-
else:
2178-
res = sNoErrors(k, y)
2179-
useLstat = false
2180-
else:
2181-
useLstat = true
2182-
else:
2183-
useLstat = true
2184-
if useLstat:
2185-
# special case of DT_UNKNOWN: some filesystems can't detect that
2186-
# entry is a directory and keep its d_type as 0=DT_UNKNOWN
2187-
if lstat(path, s) < 0'i32:
2188-
res = sGetError(wsEntryBad, y)
2189-
else:
2155+
continue
2156+
var s: Stat
2157+
let path = dir / y
2158+
if not relative:
2159+
y = path
2160+
var k = pcFile
2161+
2162+
when defined(linux) or defined(macosx) or
2163+
defined(bsd) or defined(genode) or defined(nintendoswitch):
2164+
if x.d_type != DT_UNKNOWN:
2165+
if x.d_type == DT_DIR:
2166+
k = pcDir
2167+
res = sNoErrors(k, y)
2168+
elif x.d_type == DT_LNK:
21902169
errno = 0
2191-
if S_ISDIR(s.st_mode):
2192-
k = pcDir
2193-
elif S_ISLNK(s.st_mode):
2194-
k = getSymlinkFileKind(path)
2195-
if errno == 0: # check error in getSymlinkFileKind
2170+
if dirExists(path): k = pcLinkToDir
2171+
else: k = pcLinkToFile
2172+
if errno == 0: # check error in dirExists
21962173
res = sNoErrors(k, y)
21972174
else:
21982175
res = sGetError(wsEntryBad, y)
2199-
if yieldAllowed: yield res
2200-
2201-
proc tryOpenDir*(dir: string): OpenDirStatus {.
2202-
tags: [ReadDirEffect], raises: [], since:(1,1).} =
2203-
# TODO
2204-
for step in tryWalkDir(dir):
2205-
case step.kind
2206-
of wsOpenDir: return step.openStatus
2207-
else: break # can not happen
2176+
else:
2177+
res = sNoErrors(k, y)
2178+
break beforeYield
2179+
# case of d_type==DT_UNKNOWN: some filesystems don't report
2180+
# the entry type; one should fallback to lstat
2181+
if lstat(path, s) < 0'i32:
2182+
res = sGetError(wsEntryBad, y)
2183+
else:
2184+
errno = 0
2185+
if S_ISDIR(s.st_mode):
2186+
k = pcDir
2187+
elif S_ISLNK(s.st_mode):
2188+
k = getSymlinkFileKind(path)
2189+
if errno == 0: # check error in getSymlinkFileKind
2190+
res = sNoErrors(k, y)
2191+
else:
2192+
res = sGetError(wsEntryBad, y)
2193+
yield res
22082194

22092195
iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] {.
22102196
tags: [ReadDirEffect].} =

0 commit comments

Comments
 (0)