]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
findmnt: skip shadowed entries when matching by --target
authordengbo <dengbo@deepin.org>
Thu, 25 Jun 2026 13:52:16 +0000 (21:52 +0800)
committerdengbo <dengbo@deepin.org>
Fri, 10 Jul 2026 03:39:54 +0000 (11:39 +0800)
The previous approach filtered shadowed entries in match_func() using
mnt_table_over_fs() with is_defined_match(COL_TARGET) as the trigger.
This was fragile because COL_TARGET matching is also enabled by other
code paths (source/target swap fallback in get_next_fs(), poll_match()
swap logic, and positional arguments).

Replace with the standard mountinfo iteration pattern: read
/proc/self/mountinfo backward (MNT_ITER_BACKWARD), stop at the first
match (FL_FIRSTONLY), and disable source/target swapping
(FL_NOSWAPMATCH). Since later mounts appear later in mountinfo,
backward iteration naturally finds the visible (topmost) filesystem
for the given target path.

Fixes https://github.com/util-linux/util-linux/issues/4424

misc-utils/findmnt.c

index c892bf2993c63ddab99fc20e6842c7bc13fd16f6..eca6dc74bf2dabe5d1f7f980f62a853cc2691b1c 100644 (file)
@@ -1763,6 +1763,7 @@ int main(int argc, char *argv[])
        char *outarg = NULL;
        size_t i;
        int force_tree = 0, istree = 0;
+       int force_target = 0;
 
        struct libscols_table *table = NULL;
 
@@ -2001,7 +2002,7 @@ int main(int argc, char *argv[])
                        FALLTHROUGH;
                case 'T':
                        set_match(COL_TARGET, optarg);
-                       findmnt.flags |= FL_NOSWAPMATCH;
+                       force_target = 1;
                        break;
                case 'U':
                        findmnt.flags |= FL_UNIQ;
@@ -2143,6 +2144,11 @@ int main(int argc, char *argv[])
                        findmnt.flags |= FL_NOSWAPMATCH;
        }
 
+       if (force_target) {
+               direction = MNT_ITER_BACKWARD;
+               findmnt.flags |= FL_NOSWAPMATCH | FL_FIRSTONLY;
+       }
+
        /*
         * initialize libmount
         */