]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
debuginfod 4: symbolic link traversal mode
authorFrank Ch. Eigler <fche@redhat.com>
Wed, 6 Nov 2019 23:53:31 +0000 (18:53 -0500)
committerMark Wielaard <mark@klomp.org>
Fri, 22 Nov 2019 22:56:25 +0000 (23:56 +0100)
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.

debuginfod/ChangeLog
debuginfod/debuginfod.cxx
doc/debuginfod.8
tests/ChangeLog
tests/run-debuginfod-find.sh

index 34713746350da76960bc054e6554186cb93c7d25..2870b6df93922d83ea0f4b4928ad5fb3b6eb8958 100644 (file)
@@ -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
index 359f9a24c3cb950a90c6a241648046d901012a70..8c8f2658b369067828909af52e8719a5d42f5950 100644 (file)
@@ -326,6 +326,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 },
@@ -374,6 +375,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.  */
@@ -391,6 +393,9 @@ parse_opt (int key, char *arg,
       break;
     case 'F': scan_files = true; break;
     case 'R': scan_rpms = true; break;
+    case 'L':
+      traverse_logical = true;
+      break;
     case 'D': extra_ddl.push_back(string(arg)); break;
     case 't':
       rescan_s = (unsigned) atoi(arg);
@@ -1463,8 +1468,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)
@@ -1660,7 +1664,7 @@ scan_source_file_path (const string& dir)
               throw libc_exception(f->fts_errno, string("fts/file 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;
             }
 
@@ -1931,8 +1935,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)
@@ -2062,7 +2065,7 @@ scan_source_rpm_path (const string& dir)
               throw libc_exception(f->fts_errno, string("fts/rpm 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;
             }
 
index eb1d89108c1274d011e9fefb0747f139cfbfeeae..8783df589bbb2c38a9f9c7ac84c79b9b307a933f 100644 (file)
@@ -158,6 +158,15 @@ concurrently do CPU-intensive operations like parsing an ELF file
 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.
index 42dee5c286cf3098aecffa7d4fb5b9406465aa6b..3ce7f01ae2b1a669f72c30b5ee7497139aeb4ffa 100644 (file)
@@ -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.
index eb32def6c90454593cf75aa8d9c63d79b6ff5ca6..4b31af108df1985b87f0ad159d785ab041a54bf1 100755 (executable)
@@ -20,10 +20,11 @@ set -x
 . $srcdir/test-subr.sh  # includes set -e
 
 DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
 export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
 
 # clean up trash if we were aborted early
-trap 'kill $PID1 $PID2 || true; sleep 5; rm -rf F R ${PWD}/.client_cache*; exit_cleanup' 0 1 2 3 5 9 15
+trap 'kill $PID1 $PID2 || true; sleep 5; rm -rf F R ${PWD}/.client_cache*; exit_cleanup' 0 1 2 3 5 9 15
 
 # find an unused port number
 while true; do
@@ -40,10 +41,11 @@ done
 # So we gather the LD_LIBRARY_PATH with this cunning trick:
 ldpath=`testrun sh -c 'echo $LD_LIBRARY_PATH'`
 
-mkdir F R
-# not tempfiles F R - they are directories which we clean up manually
-env DEBUGINFOD_TEST_WEBAPI_SLEEP=3 LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod -F -R -vvvv -d $DB \
--p $PORT1 -t0 -g0 R F &
+mkdir F R L
+# not tempfiles F R L - they are directories which we clean up manually
+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 -F -R -vvvv -d $DB -p $PORT1 -t0 -g0 R F L &
 PID1=$!
 sleep 3
 export DEBUGINFOD_URLS=http://localhost:$PORT1/   # or without trailing /
@@ -193,14 +195,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 -F -vvvv -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 -F -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