From b2ab9bd4a394a60bfb2b21f5cc31b6f3185fc7e5 Mon Sep 17 00:00:00 2001 From: Joshua Watt Date: Wed, 13 Sep 2023 13:04:24 -0600 Subject: bitbake: utils: Add path_is_descendant() Adds a utility that checks if one path is an descendant of another. This check uses os.path.samestat() to make it immune to symlinks and bind mounts. (Bitbake rev: c3ae45946886ee2049939dd5a205790657a7de32) Signed-off-by: Joshua Watt Signed-off-by: Alexandre Belloni Signed-off-by: Richard Purdie --- bitbake/lib/bb/utils.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index 0624a4f3e9..b401fa5ec7 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py @@ -1828,6 +1828,29 @@ def mkstemp(suffix=None, prefix=None, dir=None, text=False): prefix = tempfile.gettempprefix() + entropy return tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir, text=text) +def path_is_descendant(descendant, ancestor): + """ + Returns True if the path `descendant` is a descendant of `ancestor` + (including being equivalent to `ancestor` itself). Otherwise returns False. + Correctly accounts for symlinks, bind mounts, etc. by using + os.path.samestat() to compare paths + + May raise any exception that os.stat() raises + """ + + ancestor_stat = os.stat(ancestor) + + # Recurse up each directory component of the descendant to see if it is + # equivalent to the ancestor + check_dir = os.path.abspath(descendant).rstrip("/") + while check_dir: + check_stat = os.stat(check_dir) + if os.path.samestat(check_stat, ancestor_stat): + return True + check_dir = os.path.dirname(check_dir).rstrip("/") + + return False + # If we don't have a timeout of some kind and a process/thread exits badly (for example # OOM killed) and held a lock, we'd just hang in the lock futex forever. It is better # we exit at some point than hang. 5 minutes with no progress means we're probably deadlocked. -- cgit v1.2.3-54-g00ecf