Speed up walkDir significantly

We only know that this works on Linux and Mac OS X, so other systems use
the POSIX conforming version still. This removed the lstat call, which
is especially expensive on NFS filesystems for me.
This commit is contained in:
def
2015-02-24 16:37:54 +01:00
parent 752052e903
commit 1adebdc767
2 changed files with 20 additions and 3 deletions

View File

@@ -70,6 +70,16 @@ const
STDIN_FILENO* = 0 ## File number of stdin;
STDOUT_FILENO* = 1 ## File number of stdout;
DT_UNKNOWN* = 0
DT_FIFO* = 1
DT_CHR* = 2
DT_DIR* = 4
DT_BLK* = 6
DT_REG* = 8
DT_LNK* = 10
DT_SOCK* = 12
DT_WHT* = 14
type
TDIR* {.importc: "DIR", header: "<dirent.h>",
incompleteStruct.} = object
@@ -84,6 +94,9 @@ type
Tdirent* {.importc: "struct dirent",
header: "<dirent.h>", final, pure.} = object ## dirent_t struct
d_ino*: Tino ## File serial number.
d_off*: TOff
d_reclen*: cshort
d_type*: int8
d_name*: array [0..255, char] ## Name of entry.
Tflock* {.importc: "struct flock", final, pure,

View File

@@ -1299,10 +1299,14 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {.
if y != "." and y != "..":
var s: TStat
y = dir / y
if lstat(y, s) < 0'i32: break
var k = pcFile
if S_ISDIR(s.st_mode): k = pcDir
if S_ISLNK(s.st_mode): k = succ(k)
when defined(linux) or defined(macosx):
if x.d_type == DT_DIR: k = pcDir
if x.d_type == DT_LNK: k = succ(k)
else:
if lstat(y, s) < 0'i32: break
if S_ISDIR(s.st_mode): k = pcDir
if S_ISLNK(s.st_mode): k = succ(k)
yield (k, y)
discard closedir(d)