On Tue, Nov 28, 2017 at 02:04:53PM -0800, Jonathan Nieder wrote: > > What should happen in the DT_LNK case? Should the same logic trip for > it as well so we can distinguish between a symlink to a directory and > other symlinks? >
The filesystems that i tested on all return DT_UNKNOWN for a symlink or hardlink. Even when they return proper type for a file or directory. However, if the filesystem ever sets type to DT_LNK glob needs to treat it like DT_UNKNOWN. regards, Dmitry diff --git a/ChangeLog b/ChangeLog index ffeb208132..fb76fc1415 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2017-11-28 Dmitry Goncharov <dgoncha...@users.sf.net> + + [BZ #22513] + * posix/glob.c (glob_in_dir): Make pattern with a trailing slash + match directores only. + * posix/globtest.sh: Add tests. + 2017-11-13 Florian Weimer <fwei...@redhat.com> * support/next_to_fault.h, support/next_to_fault.c: New files. diff --git a/posix/glob.c b/posix/glob.c index cb39779d07..47e67907cd 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -1342,7 +1342,33 @@ glob_in_dir (const char *pattern, const char *directory, int flags, if (flags & GLOB_ONLYDIR) switch (readdir_result_type (d)) { - case DT_DIR: case DT_LNK: case DT_UNKNOWN: break; + case DT_DIR: break; + case DT_LNK: case DT_UNKNOWN: + { + int dir; + size_t namlen = strlen (d.name); + size_t fullsize; + bool alloca_fullname + = (! size_add_wrapv (dirlen + 1, namlen + 1, &fullsize) + && glob_use_alloca (alloca_used, fullsize)); + char *fullname; + if (alloca_fullname) + fullname = alloca_account (fullsize, alloca_used); + else + { + fullname = malloc (fullsize); + if (fullname == NULL) + return GLOB_NOSPACE; + } + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), + "/", 1), + d.name, namlen + 1); + dir = is_dir (fullname, flags, pglob); + if (__glibc_unlikely (!alloca_fullname)) + free (fullname); + if (dir) + break; + } default: continue; } diff --git a/posix/globtest.sh b/posix/globtest.sh index 73f7ae31cc..4a062ea507 100755 --- a/posix/globtest.sh +++ b/posix/globtest.sh @@ -43,13 +43,22 @@ export LC_ALL # Create the arena testdir=${common_objpfx}posix/globtest-dir +testdir2=${common_objpfx}posix/globtest-dir2 testout=${common_objpfx}posix/globtest-out rm -rf $testdir $testout mkdir $testdir +mkdir $testdir2 +mkdir $testdir2/hello1d +ln -s $testdir2/hello1d $testdir2/hello1ds +mkdir $testdir2/hello2d +echo 1 > $testdir2/hello1f +ln -s $testdir2/hello1f $testdir2/hello1fs +echo 2 > $testdir2/hello2f +ln $testdir2/hello2f $testdir2/hello2fl cleanup() { chmod 777 $testdir/noread - rm -fr $testdir $testout + rm -fr $testdir $testdir2 $testout } trap cleanup 0 HUP INT QUIT TERM @@ -815,6 +824,45 @@ if test $failed -ne 0; then result=1 fi +# Test that if the specified glob ends with a slash then only directories are +# matched. +# First run with the glob that has no slash to demonstrate presence of a slash +# makes a difference. +failed=0 +${test_program_prefix} \ +${common_objpfx}posix/globtest "$testdir2" "hello*" | +sort > $testout +cat <<"EOF" | $CMP - $testout >> $logfile || failed=1 +`hello1d' +`hello1ds' +`hello1f' +`hello1fs' +`hello2d' +`hello2f' +`hello2fl' +EOF + +if test $failed -ne 0; then + echo "pattern+meta test failed" >> $logfile + result=1 +fi + +# The same pattern+meta test with a slash this time. +failed=0 +${test_program_prefix} \ +${common_objpfx}posix/globtest "$testdir2" "hello*/" | +sort > $testout +cat <<"EOF" | $CMP - $testout >> $logfile || failed=1 +`hello1d/' +`hello1ds/' +`hello2d/' +EOF + +if test $failed -ne 0; then + echo "pattern+meta+slash test failed" >> $logfile + result=1 +fi + if test $result -eq 0; then echo "All OK." > $logfile fi