我想知道同样的事情 - “这个 lstat 的目的是什么?它会影响 glob() 的返回吗?”
在 bsd_glob.c glob2() 中,我注意到 if 分支中的 g_stat 调用需要设置 GLOB_MARK 标志,我还注意到之前对 g_lstat 的调用没有受到标志检查的保护。当到达模式结束时,两者都在 if 分支内。如果我在 perl-5.12.4/ext/File-Glob/bsd_glob.c 的 glob2 函数中删除这两行
- if (g_lstat(pathbuf, &sb, pglob))
- return(0);
唯一失败的 perl 测试(make test)是 ext/File-Glob/t/basic.t 中的测试 5:
not ok 5
# Failed test at ../ext/File-Glob/t/basic.t line 92.
# Structures begin differing at:
# $got->[0] = 'asdfasdf'
# $expected->[0] = Does not exist
t/basic.t 中的测试 5 是
# check nonexistent checks
# should return an empty list
# XXX since errfunc is NULL on win32, this test is not valid there
@a = bsd_glob("asdfasdf", 0);
SKIP: {
skip $^O, 1 if $^O eq 'MSWin32' || $^O eq 'NetWare';
is_deeply(\@a, []);
}
如果我将删除的 2 行替换为:
+ if (!((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR)))){
+ if (g_lstat(pathbuf, &sb, pglob))
+ return(0);
+ }
我没有看到 Linux x86_64 (RHEL6.3 2.6.32-358.11.1.el6.x86_64) 上的 perl-5.12.4 的“make test”有任何失败,并且在使用时:
strace -fe trace=lstat perl -e 'use File::Glob q{:glob};
print scalar bsd_glob(q{/var/log/*},GLOB_NOCHECK)'
我不再看到目录中每个文件的 lstat 调用。我并不是说针对 glob (File-Glob) 的 perl 测试是全面的(它们不是),或者这样的更改不会破坏现有行为(这似乎很可能)。据我所知,这个 (g_l)stat 调用的代码在 24 年前的 1990 年存在于 original-bsd/lib/libc/gen/glob.c 中。
另见:
- Chapter 6. Benchmarking Perl of "Mastering Perl" by brian d foy,Randal L. Schwartz 包含一个比较代码的部分,其中比较了使用 glob() 和 opendir() 的代码。
- 1991 年 Dick Dunn 的 comp.unix.wizards 中的“future globs (was "UNIX mind...")”。
- 1986 年 7 月 Guido van Rossum 的 Usenet 新闻组 mod.sources "'Globbing' library routine (glob)" - 我在这段代码中没有看到对 "stat" 的引用。