* 'whereis' of https://github.com/ferivoz/util-linux:
  whereis: extend test case
  whereis: filter bin, man and src differently
  whereis: do not strip suffixes
  whereis: do not ignore trailing numbers
  whereis: add --disable-whereis to configure
  whereis: add lib32 directories
  whereis: support zst compressed man pages
  whereis: fix out of boundary read
This commit is contained in:
Karel Zak 2020-11-06 09:44:52 +01:00
commit de9cbcdcef
5 changed files with 59 additions and 32 deletions

View File

@ -1651,7 +1651,11 @@ if test "x$matriplet" != "x"; then
AC_DEFINE_UNQUOTED([MULTIARCHTRIPLET], ["$matriplet"], AC_DEFINE_UNQUOTED([MULTIARCHTRIPLET], ["$matriplet"],
["Multi-arch triplet for whereis library search path"]) ["Multi-arch triplet for whereis library search path"])
fi fi
UL_BUILD_INIT([whereis], [yes]) AC_ARG_ENABLE([whereis],
AS_HELP_STRING([--disable-whereis], [do not build whereis]),
[], [UL_DEFAULT_ENABLE([whereis], [check])]
)
UL_BUILD_INIT([whereis])
AM_CONDITIONAL([BUILD_WHEREIS], [test "x$build_whereis" = xyes]) AM_CONDITIONAL([BUILD_WHEREIS], [test "x$build_whereis" = xyes])
UL_BUILD_INIT([getopt], [yes]) UL_BUILD_INIT([getopt], [yes])

View File

@ -42,11 +42,7 @@ whereis \- locate the binary, source, and manual page files for a command
.SH DESCRIPTION .SH DESCRIPTION
.B whereis .B whereis
locates the binary, source and manual files for the specified command names. locates the binary, source and manual files for the specified command names.
The supplied names are first stripped of leading pathname components and any The supplied names are first stripped of leading pathname components.
(single) trailing extension of the form
.BI . ext
(for example:
.BR .c )
Prefixes of Prefixes of
.B s. .B s.
resulting from use of source code control are also dealt with. resulting from use of source code control are also dealt with.

View File

@ -107,10 +107,12 @@ static const char *bindirs[] = {
"/usr/local/lib/" MULTIARCHTRIPLET, "/usr/local/lib/" MULTIARCHTRIPLET,
#endif #endif
"/usr/lib", "/usr/lib",
"/usr/lib32",
"/usr/lib64", "/usr/lib64",
"/etc", "/etc",
"/usr/etc", "/usr/etc",
"/lib", "/lib",
"/lib32",
"/lib64", "/lib64",
"/usr/games", "/usr/games",
"/usr/games/bin", "/usr/games/bin",
@ -390,29 +392,32 @@ static void free_dirlist(struct wh_dirlist **ls0, int type)
} }
static int filename_equal(const char *cp, const char *dp) static int filename_equal(const char *cp, const char *dp, int type)
{ {
int i = strlen(dp); int i = strlen(dp);
DBG(SEARCH, ul_debug("compare '%s' and '%s'", cp, dp)); DBG(SEARCH, ul_debug("compare '%s' and '%s'", cp, dp));
if (dp[0] == 's' && dp[1] == '.' && filename_equal(cp, dp + 2)) if (type & SRC_DIR &&
dp[0] == 's' && dp[1] == '.' && filename_equal(cp, dp + 2, type))
return 1; return 1;
if (!strcmp(dp + i - 2, ".Z")) if (type & MAN_DIR) {
i -= 2; if (i > 1 && !strcmp(dp + i - 2, ".Z"))
else if (!strcmp(dp + i - 3, ".gz")) i -= 2;
i -= 3; else if (i > 2 && !strcmp(dp + i - 3, ".gz"))
else if (!strcmp(dp + i - 3, ".xz")) i -= 3;
i -= 3; else if (i > 2 && !strcmp(dp + i - 3, ".xz"))
else if (!strcmp(dp + i - 4, ".bz2")) i -= 3;
i -= 4; else if (i > 3 && !strcmp(dp + i - 4, ".bz2"))
i -= 4;
else if (i > 3 && !strcmp(dp + i - 4, ".zst"))
i -= 4;
}
while (*cp && *dp && *cp == *dp) while (*cp && *dp && *cp == *dp)
cp++, dp++, i--; cp++, dp++, i--;
if (*cp == 0 && *dp == 0) if (*cp == 0 && *dp == 0)
return 1; return 1;
while (isdigit(*dp)) if (!(type & BIN_DIR) && *cp == 0 && *dp++ == '.') {
dp++;
if (*cp == 0 && *dp++ == '.') {
--i; --i;
while (i > 0 && *dp) while (i > 0 && *dp)
if (--i, *dp++ == '.') if (--i, *dp++ == '.')
@ -422,7 +427,8 @@ static int filename_equal(const char *cp, const char *dp)
return 0; return 0;
} }
static void findin(const char *dir, const char *pattern, int *count, char **wait) static void findin(const char *dir, const char *pattern, int *count,
char **wait, int type)
{ {
DIR *dirp; DIR *dirp;
struct dirent *dp; struct dirent *dp;
@ -434,7 +440,7 @@ static void findin(const char *dir, const char *pattern, int *count, char **wait
DBG(SEARCH, ul_debug("find '%s' in '%s'", pattern, dir)); DBG(SEARCH, ul_debug("find '%s' in '%s'", pattern, dir));
while ((dp = readdir(dirp)) != NULL) { while ((dp = readdir(dirp)) != NULL) {
if (!filename_equal(pattern, dp->d_name)) if (!filename_equal(pattern, dp->d_name, type))
continue; continue;
if (uflag && *count == 0) if (uflag && *count == 0)
@ -467,9 +473,6 @@ static void lookup(const char *pattern, struct wh_dirlist *ls, int want)
want & BIN_DIR ? "bin" : "", want & BIN_DIR ? "bin" : "",
want & MAN_DIR ? "man" : "", want & MAN_DIR ? "man" : "",
want & SRC_DIR ? "src" : "")); want & SRC_DIR ? "src" : ""));
p = strrchr(patbuf, '.');
if (p)
*p = '\0';
if (!uflag) if (!uflag)
/* if -u not specified then we always print the pattern */ /* if -u not specified then we always print the pattern */
@ -477,7 +480,7 @@ static void lookup(const char *pattern, struct wh_dirlist *ls, int want)
for (; ls; ls = ls->next) { for (; ls; ls = ls->next) {
if ((ls->type & want) && ls->path) if ((ls->type & want) && ls->path)
findin(ls->path, patbuf, &count, &wait); findin(ls->path, patbuf, &count, &wait, ls->type);
} }
free(wait); free(wait);

View File

@ -1 +1,5 @@
success fsck success
fsck.ext4 success
python success
python3 success
python3.8 success

View File

@ -20,11 +20,31 @@ ts_init "$*"
ts_check_test_command "$TS_CMD_WHEREIS" ts_check_test_command "$TS_CMD_WHEREIS"
LS_COUNT=$($TS_CMD_WHEREIS ls | wc -w) BIN_DIR="$(mktemp -d "${TS_OUTDIR}/binXXXXXXXXXXXXX")"
if [ $LS_COUNT -lt 2 ]; then MAN_DIR="$(mktemp -d "${TS_OUTDIR}/manXXXXXXXXXXXXX")"
echo "ls binary nor manual not found?" > $TS_OUTPUT touch "$BIN_DIR/fsck"
else touch "$MAN_DIR/fsck.8.zst"
echo "success" > $TS_OUTPUT touch "$BIN_DIR/fsck.ext4"
fi touch "$MAN_DIR/fsck.ext4.8.zst"
touch "$BIN_DIR/fsck.minix"
touch "$BIN_DIR/python"
touch "$MAN_DIR/python.1.gz"
touch "$BIN_DIR/python3"
touch "$MAN_DIR/python3.1"
touch "$BIN_DIR/python3.8"
touch "$BIN_DIR/python3.8-config"
touch "$MAN_DIR/python3.8.1"
for COMMAND in fsck fsck.ext4 python python3 python3.8
do
COUNT=$($TS_CMD_WHEREIS -B $BIN_DIR -M $MAN_DIR -f $COMMAND | wc -w)
if [ $COUNT -eq 3 ]; then
echo "$COMMAND success" >> $TS_OUTPUT
else
echo "$COMMAND failure" >> $TS_OUTPUT
fi
done
rm -rf "$BIN_DIR" "$MAN_DIR"
ts_finalize ts_finalize