2013-05-09 33 views
6

Nhìn vào hành vi trong this question, tôi đã rất ngạc nhiên khi thấy rằng perl lstat() s mỗi con đường phù hợp với một mô hình glob:Tại sao các mục nhập phù hợp với glob lstat?

$ mkdir dir 
$ touch dir/{foo,bar,baz}.txt 
$ strace -e trace=lstat perl -E 'say $^V; <dir/b*>' 
v5.10.1 
lstat("dir/baz.txt", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0 
lstat("dir/bar.txt", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0 

tôi thấy hành vi tương tự trên hệ thống Linux của tôi với glob(pattern)<pattern>, và với các phiên bản sau này của perl.

Kỳ vọng của tôi là hình cầu chỉ đơn giản là opendir/readdir dưới mui xe, và rằng nó sẽ không cần phải kiểm tra các tên đường dẫn thực tế mà nó đang tìm kiếm.

Mục đích của số lstat này là gì? Nó có ảnh hưởng đến sự trở lại của glob() s không?

+0

@mpapec, tôi sẽ cập nhật với kỳ vọng của mình khi tiếp theo ở thiết bị đầu cuối, cảm ơn. – pilcrow

+0

Chỉ cần một không: Tôi đã phải thay đổi 'lstat' để' lstat64' trên hệ thống của tôi. – choroba

Trả lời

8

Hành vi lạ này đã là noticed before on PerlMonks. Nó chỉ ra rằng glob cuộc gọi lstat để hỗ trợ GLOB_MARK cờ của quốc gia, trong đó có hiệu quả mà:

Mỗi tên đường dẫn đó là một thư mục phù hợp với mô hình có một dấu gạch chéo nối.

Để tìm hiểu xem mục nhập thư mục có đề cập đến một thư mục con hay không, bạn cần phải stat thư mục đó. Điều này dường như được thực hiện ngay cả khi lá cờ không được đưa ra.

+0

Điều đó dường như chính xác, cảm ơn. – pilcrow

2

Tôi đã tự hỏi điều tương tự - "Mục đích của lstat này là gì? Liệu nó ảnh hưởng đến sự trở lại của glob() s?"

Trong bsd_glob.c glob2() Tôi nhận thấy cuộc gọi g_stat trong một nhánh nếu yêu cầu cờ GLOB_MARK được đặt, tôi cũng nhận thấy cuộc gọi tới g_lstat ngay trước khi không được kiểm soát bằng cờ. Cả hai đều nằm trong một nhánh nếu cho đến khi kết thúc mẫu. Nếu tôi loại bỏ những 2 dòng trong hàm glob2 trong/File-Glob/bsd_glob.c perl-5.12.4/ext

- if (g_lstat(pathbuf, &sb, pglob)) 
-  return(0); 

test chỉ perl (làm thử nghiệm) mà không là kiểm tra 5 trong ext/file-Glob/t/basic.t với:

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 

thử nghiệm 5 trong t/basic.t là

# 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, []); 
} 

Nếu tôi thay thế 2 dây chuyền loại bỏ bằng:

+ if (!((pglob->gl_flags & GLOB_NOCHECK) || 
+   ((pglob->gl_flags & GLOB_NOMAGIC) && 
+   !(pglob->gl_flags & GLOB_MAGCHAR)))){ 
+  if (g_lstat(pathbuf, &sb, pglob)) 
+  return(0); 
+ } 

Tôi không thấy bất kỳ thất bại từ "make test" cho perl-5.12.4 trên x86_64 linux (RHEL6.3 2.6.32-358.11.1.el6.x86_64) và khi sử dụng:

strace -fe trace=lstat perl -e 'use File::Glob q{:glob}; 
           print scalar bsd_glob(q{/var/log/*},GLOB_NOCHECK)' 

Tôi không còn thấy các cuộc gọi lstat cho mỗi tệp trong thư mục. Tôi không muốn đề nghị rằng các bài kiểm tra perl cho glob (File-Glob) là toàn diện (chúng không), hoặc thay đổi như thế này sẽ không phá vỡ hành vi hiện tại (điều này có vẻ như). Theo như tôi có thể nói mã với điều này (g_l) gọi stat tồn tại gốc-bsd/lib/libc/gen/glob.c 24 năm trước đây vào năm 1990.

Xem thêm:

  • Chương 6.Điểm chuẩn Perl của "Mastering Perl" Bởi brian d foy, Randal L. Schwartz chứa một phần về so sánh mã nơi mã sử dụng glob() và opendir() được so sánh.
  • "tương lai globs (là" UNIX mindset ... ")" trong comp.unix.wizards từ Dick Dunn vào năm 1991.
  • Usenet newsgroup mod.sources "'Globbing' thư viện thường lệ (glob)" từ Guido van Rossum vào tháng 7 năm 1986 - Tôi không thấy tham chiếu đến "stat" trong mã này.
Các vấn đề liên quan