summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@redhat.com>2019-11-06 18:53:31 -0500
committerFrank Ch. Eigler <fche@redhat.com>2019-11-12 10:13:50 -0500
commit7b956cdd801656a8abed1f444e4b838a90c42dde (patch)
tree2ebb27d620e81d5734d01b0b9e15793bc74cf47e
parent3c2ea78a22344b046a8c287fa1921f1f450d3551 (diff)
downloadelfutils-7b956cdd801656a8abed1f444e4b838a90c42dde.tar.gz
debuginfod 4: symbolic link traversal mode
In order to support file/rpm archives that are organized via symlink trees, add an "-L" option to debuginfod, meaning about the same as for find(1) or ls(1): to traverse rather than ignore symlinks.
-rw-r--r--debuginfod/ChangeLog5
-rw-r--r--debuginfod/debuginfod.815
-rw-r--r--debuginfod/debuginfod.cxx15
-rw-r--r--tests/ChangeLog5
-rwxr-xr-xtests/run-debuginfod-find.sh39
5 files changed, 53 insertions, 26 deletions
diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index 34713746..2870b6df 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -1,3 +1,8 @@
+2019-11-06 Frank Ch. Eigler <fche@redhat.com>
+
+ * debuginfod.cxx: Add new -L (symlink-following) mode.
+ * debuginfod.8: Document it.
+
2019-11-04 Frank Ch. Eigler <fche@redhat.com>
* debuginfo-client.c (debuginfod_set_progressfn): New function
diff --git a/debuginfod/debuginfod.8 b/debuginfod/debuginfod.8
index 02059a11..6b45dee6 100644
--- a/debuginfod/debuginfod.8
+++ b/debuginfod/debuginfod.8
@@ -35,14 +35,14 @@ debuginfod servers, it queries them for the same information, just as
relays the file content to the original requester.
Each listed PATH creates a thread to scan for matching
-ELF/DWARF/source files under the given directory. Source files are
+ELF/DWARF/source files under the given physical directory. Source files are
matched with DWARF files based on the AT_comp_dir (compilation
directory) attributes inside it. Duplicate directories are ignored.
You may use a file name for a PATH, but source code indexing may be
incomplete; prefer using a directory that contains the binaries.
Each listed PATH also creates a thread to scan for ELF/DWARF/source
-files contained in matching RPMs under the given directory. Duplicate
+files contained in matching RPMs under the given physical directory. Duplicate
directories are ignored. You may use a file name for a PATH, but
source code indexing may be incomplete; prefer using a directory that
contains normal RPMs alongside debuginfo/debugsource RPMs. Because of
@@ -50,7 +50,7 @@ complications such as DWZ-compressed debuginfo, may require \fItwo\fP
scan passes to identify all source code.
If no PATH is listed, then \fBdebuginfod\fP will simply serve content
-that it scanned into its index in previous runs.
+that it scanned into its index in previous runs: the data is cumulative.
File names must match extended regular expressions given by the \-I
option and not the \-X option (if any) in order to be considered.
@@ -134,6 +134,15 @@ or an RPM. The default is the number of processors on the system;
the minimum is 1.
.TP
+.B "\-L"
+Traverse symbolic links encountered during traversal of the PATHs,
+including across devices - as in \fIfind\ -L\fP. The default is to
+traverse the physical directory structure only, stay on the same
+device, and ignore symlinks - as in \fIfind\ -P\ -xdev\fP. Caution: a
+loops in the symbolic directory tree might lead to \fIinfinite
+traversal\fP.
+
+.TP
.B "\-v"
Increase verbosity of logging to the standard error file descriptor.
May be repeated to increase details. The default verbosity is 0.
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
index fe8706cf..7c7a0c5d 100644
--- a/debuginfod/debuginfod.cxx
+++ b/debuginfod/debuginfod.cxx
@@ -325,6 +325,7 @@ static const struct argp_option options[] =
// "source-oci-imageregistry" ...
{ NULL, 0, NULL, 0, "Options:", 2 },
+ { "logical", 'L', NULL, 0, "Follow symlinks, default=ignore.", 0 },
{ "rescan-time", 't', "SECONDS", 0, "Number of seconds to wait between rescans, 0=disable.", 0 },
{ "groom-time", 'g', "SECONDS", 0, "Number of seconds to wait between database grooming, 0=disable.", 0 },
{ "maxigroom", 'G', NULL, 0, "Run a complete database groom/shrink pass at startup.", 0 },
@@ -371,6 +372,7 @@ static vector<string> extra_ddl;
static regex_t file_include_regex;
static regex_t file_exclude_regex;
static int test_webapi_sleep; /* testing only */
+static bool traverse_logical;
/* Handle program arguments. */
@@ -388,6 +390,9 @@ parse_opt (int key, char *arg,
break;
case 'F': break; // ignored; blog post compatibility
case 'R': break; // ignored; blog post compatibility
+ case 'L':
+ traverse_logical = true;
+ break;
case 'D': extra_ddl.push_back(string(arg)); break;
case 't':
rescan_s = (unsigned) atoi(arg);
@@ -1459,8 +1464,7 @@ scan_source_file_path (const string& dir)
unsigned fts_scanned=0, fts_regex=0, fts_cached=0, fts_debuginfo=0, fts_executable=0, fts_sourcefiles=0;
FTS *fts = fts_open (dirs,
- FTS_PHYSICAL /* don't follow symlinks */
- | FTS_XDEV /* don't cross devices/mountpoints */
+ (traverse_logical ? FTS_LOGICAL : FTS_PHYSICAL|FTS_XDEV)
| FTS_NOCHDIR /* multithreaded */,
NULL);
if (fts == NULL)
@@ -1655,7 +1659,7 @@ scan_source_file_path (const string& dir)
throw libc_exception(f->fts_errno, string("fts/F traversal ") + string(f->fts_path));
default:
- case FTS_SL: /* NB: don't enter symbolic links into the database */
+ case FTS_SL: /* ignore symlinks; seen in non-L mode only */
break;
}
@@ -1922,8 +1926,7 @@ scan_source_rpm_path (const string& dir)
unsigned fts_executable=0, fts_rpm = 0, fts_sref=0, fts_sdef=0;
FTS *fts = fts_open (dirs,
- FTS_PHYSICAL /* don't follow symlinks */
- | FTS_XDEV /* don't cross devices/mountpoints */
+ (traverse_logical ? FTS_LOGICAL : FTS_PHYSICAL|FTS_XDEV)
| FTS_NOCHDIR /* multithreaded */,
NULL);
if (fts == NULL)
@@ -2056,7 +2059,7 @@ scan_source_rpm_path (const string& dir)
throw libc_exception(f->fts_errno, string("fts/R traversal ") + string(f->fts_path));
default:
- case FTS_SL: /* NB: don't enter symbolic links into the database */
+ case FTS_SL: /* ignore symlinks; seen in non-L mode only */
break;
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 7b091158..3d50ee86 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2019-11-06 Frank Ch. Eigler <fche@redhat.com>
+
+ * run-debuginfod-find.sh: Test debuginfod -L mode. Drop
+ plain debuginfo-find help-output-comparison.
+
2019-11-04 Frank Ch. Eigler <fche@redhat.com>
* run-debuginfod-find.sh: Test debuginfod-find -v progress mode.
diff --git a/tests/run-debuginfod-find.sh b/tests/run-debuginfod-find.sh
index fe38eaac..64490107 100755
--- a/tests/run-debuginfod-find.sh
+++ b/tests/run-debuginfod-find.sh
@@ -22,10 +22,11 @@ set -x
testfiles testfile-debuginfod-0.rpm testfile-debuginfod-1.rpm testfile-debuginfod-2.rpm
DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
# clean up trash if we were aborted early
-trap 'set +e; kill $PID1 $PID2; rm -rf F R ${PWD}/.client_cache*; exit_cleanup; exit 0' 0 1 2 3 5 9 15
+trap 'kill $PID1 $PID2 || true; rm -rf F R L ${PWD}/.client_cache*; exit_cleanup' 0 1 2 3 5 9 15
# find an unused port number
while true; do
@@ -42,10 +43,11 @@ done
# So we gather the LD_LIBRARY_PATH with this cunning trick:
ldpath=`testrun sh -c 'echo $LD_LIBRARY_PATH'`
-mkdir F R
-tempfiles F R
-env DEBUGINFOD_TEST_WEBAPI_SLEEP=3 LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod -vvvv -d $DB \
--p $PORT1 -t0 -g0 R F &
+mkdir F R L
+tempfiles F R L
+ln -s ${abs_builddir}/dwfllines L/foo # any program not used elsewhere in this test
+
+env DEBUGINFOD_TEST_WEBAPI_SLEEP=3 LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod -vvvv -d $DB -p $PORT1 -t0 -g0 R F L &
PID1=$!
sleep 3
export DEBUGINFOD_URLS=http://localhost:$PORT1/ # or without trailing /
@@ -171,14 +173,28 @@ done
export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache2
mkdir -p $DEBUGINFOD_CACHE_PATH
# NB: inherits the DEBUGINFOD_URLS to the first server
-env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod -d ${DB}_2 -p $PORT2 &
+# NB: run in -L symlink-following mode for the L subdir
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod -vvvv -d ${DB}_2 -p $PORT2 -L L &
PID2=$!
+tempfiles ${DB}_2
sleep 3
# have clients contact the new server
export DEBUGINFOD_URLS=http://localhost:$PORT2
testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog 1
+# confirm that first server can't resolve symlinked info in L/ but second can
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+ -a L/foo | grep 'Build ID' | cut -d ' ' -f 7`
+file L/foo
+file -L L/foo
+export DEBUGINFOD_URLS=http://localhost:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+export DEBUGINFOD_URLS=http://localhost:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+
# test parallel queries in client
export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache3
mkdir -p $DEBUGINFOD_CACHE_PATH
@@ -209,15 +225,4 @@ testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog 1
testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID2 && false || true
-########################################################################
-
-# Ensure debuginfod-find can be safely called with no arguments.
-# Use a relative path to prevent automatic line breaks in the output
-# due to excessive characters.
-testrun_compare ../../debuginfod/debuginfod-find <<EOF
-Usage: ../../debuginfod/debuginfod-find debuginfo BUILDID
- or: ../../debuginfod/debuginfod-find executable BUILDID
- or: ../../debuginfod/debuginfod-find source BUILDID /FILENAME
-EOF
-
exit 0