[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] posix: if glob has a trailing slash match directories only.
From: |
Dmitry Goncharov |
Subject: |
Re: [PATCH] posix: if glob has a trailing slash match directories only. |
Date: |
Thu, 30 Nov 2017 00:01:19 -0500 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
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 <address@hidden>
+
+ [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 <address@hidden>
* 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