aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system/fatrace/README3
-rw-r--r--system/fatrace/fatrace.SlackBuild26
-rw-r--r--system/fatrace/fatrace.info8
-rw-r--r--system/fatrace/patches/0001-Let-filter-distinguish-between-and.patch45
-rw-r--r--system/fatrace/patches/0002-Help-text-formatting.patch54
-rw-r--r--system/fatrace/patches/0003-Add-option-d-dir.patch320
-rw-r--r--system/fatrace/slack-desc2
7 files changed, 443 insertions, 15 deletions
diff --git a/system/fatrace/README b/system/fatrace/README
index edd2a3600c..d158bdab31 100644
--- a/system/fatrace/README
+++ b/system/fatrace/README
@@ -12,6 +12,5 @@ serves as a starting point for bug reports or optimizing a particular
installation.
fatrace has self-test scripts that can be run during the build. These
-are disabled by default, because they create a file outside of the
-temp directory (/etc/test.txt). If you want to run the tests, export
+are disabled by default. If you want to run the tests, export
RUNTESTS=yes in the environment.
diff --git a/system/fatrace/fatrace.SlackBuild b/system/fatrace/fatrace.SlackBuild
index e710598694..77203c99a0 100644
--- a/system/fatrace/fatrace.SlackBuild
+++ b/system/fatrace/fatrace.SlackBuild
@@ -7,6 +7,10 @@
# Licensed under the WTFPL. See http://www.wtfpl.net/txt/copying/ for details.
+# 20250916 bkw:
+# - update for v0.19.1.
+# - switch to upstream's github, instead of launchpad.
+# - add a couple of post-release patches from upstream git.
# 20250126 bkw: update for v0.18.0.
# 20230509 bkw:
# - new maintainer.
@@ -17,7 +21,7 @@
cd $(dirname $0) ; CWD=$(pwd)
PRGNAM=fatrace
-VERSION=${VERSION:-0.18.0}
+VERSION=${VERSION:-0.19.1}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
PKGTYPE=${PKGTYPE:-tgz}
@@ -55,12 +59,20 @@ rm -rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -rf $PRGNAM-$VERSION
-tar xvf $CWD/${PRGNAM}_${VERSION}.orig.tar.gz
+tar xvf $CWD/$PRGNAM-$VERSION.tar.gz
cd $PRGNAM-$VERSION
chown -R root:root .
find -L . -perm /111 -a \! -perm 755 -a -exec chmod 755 {} + -o \
\! -perm /111 -a \! -perm 644 -a -exec chmod 644 {} +
+# 20250916 bkw: these patches will be in the next release. One is a
+# fix for a real bug (the < and > thing) and one adds a *very* useful
+# option (-d).
+for i in $CWD/patches/*.patch; do
+ echo "=== Applying $( basename $i )"
+ patch -p1 < $i
+done
+
sed -i -e "/^CFLAGS/s,-O2,$SLKCFLAGS," \
-e 's,share/man,man,' \
-e 's,-Werror,,' \
@@ -71,17 +83,15 @@ strip $PRGNAM
make install DESTDIR=$PKG PREFIX=/usr
gzip $PKG/usr/man/man*/*
-# This is disabled by default because it creates (and deletes) an
-# /etc/test.txt (outside of $TMP).
+# This is disabled by default because it takes a while to run,
+# and will fail on a custom kernel that lacks btrfs.
if [ "${RUNTESTS:-no}" = "yes" ]; then
- # Tests assume wrong path (our /usr/bin/head is a symlink to /bin/head)
- sed -i 's,/usr/bin/,/bin/,' tests/fatrace
- sh tests/run
+ python3 -m unittest -v
fi
PKGDOC=$PKG/usr/doc/$PRGNAM-$VERSION
mkdir -p $PKGDOC
-cp -a COPYING NEWS $PKGDOC
+cp -a COPYING README* $PKGDOC
cat $CWD/$PRGNAM.SlackBuild > $PKGDOC/$PRGNAM.SlackBuild
mkdir -p $PKG/install
diff --git a/system/fatrace/fatrace.info b/system/fatrace/fatrace.info
index 65c9f70b78..72f2420543 100644
--- a/system/fatrace/fatrace.info
+++ b/system/fatrace/fatrace.info
@@ -1,8 +1,8 @@
PRGNAM="fatrace"
-VERSION="0.18.0"
-HOMEPAGE="https://launchpad.net/fatrace"
-DOWNLOAD="https://launchpad.net/debian/+archive/primary/+sourcefiles/fatrace/0.18.0-1/fatrace_0.18.0.orig.tar.gz"
-MD5SUM="857235823c3a5f78f56645dafd82bd8a"
+VERSION="0.19.1"
+HOMEPAGE="https://github.com/martinpitt/fatrace"
+DOWNLOAD="https://github.com/martinpitt/fatrace/archive/0.19.1/fatrace-0.19.1.tar.gz"
+MD5SUM="b65acc61fb72ca8fd196248cb3b5d618"
DOWNLOAD_x86_64=""
MD5SUM_x86_64=""
REQUIRES=""
diff --git a/system/fatrace/patches/0001-Let-filter-distinguish-between-and.patch b/system/fatrace/patches/0001-Let-filter-distinguish-between-and.patch
new file mode 100644
index 0000000000..4d427375f3
--- /dev/null
+++ b/system/fatrace/patches/0001-Let-filter-distinguish-between-and.patch
@@ -0,0 +1,45 @@
+From 33370a8c97086d7494c9bf0dd0ccd15cdcf497cb Mon Sep 17 00:00:00 2001
+From: Axel Svensson <mail@axelsvensson.com>
+Date: Thu, 4 Sep 2025 15:33:56 +0200
+Subject: [PATCH 1/3] Let --filter distinguish between < and >
+
+---
+ fatrace.8 | 5 ++---
+ fatrace.c | 4 +++-
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/fatrace.8 b/fatrace.8
+index 782669b..7117ee2 100644
+--- a/fatrace.8
++++ b/fatrace.8
+@@ -191,9 +191,8 @@ Ignore events for this process ID. Can be specified multiple times.
+ .TP
+ .B \-f \fITYPES\fR, \fB\-\-filter=\fITYPES
+ Show only the given event types. \fBTYPES\fR is a list of
+-.BR C ", " R ", " O ", " W ", " D ", " + ", or " <
+-with the above meanings. \fB<\fR and \fB>\fR both mean "move" and will always
+-enable both directions.
++.BR C ", " R ", " O ", " W ", " D ", " + ", " < ", or " >
++with the above meanings.
+
+ E. g. use \fB\-\-filter=OC\fR to only show open and close events.
+
+diff --git a/fatrace.c b/fatrace.c
+index bd0102f..e683535 100644
+--- a/fatrace.c
++++ b/fatrace.c
+@@ -749,8 +749,10 @@ parse_args (int argc, char** argv)
+ option_filter_mask |= FAN_DELETE;
+ break;
+ case '<':
++ option_filter_mask |= FAN_MOVED_FROM;
++ break;
+ case '>':
+- option_filter_mask |= FAN_MOVE;
++ option_filter_mask |= FAN_MOVED_TO;
+ break;
+ #endif
+ default:
+--
+2.46.3
+
diff --git a/system/fatrace/patches/0002-Help-text-formatting.patch b/system/fatrace/patches/0002-Help-text-formatting.patch
new file mode 100644
index 0000000000..3b7f3d92de
--- /dev/null
+++ b/system/fatrace/patches/0002-Help-text-formatting.patch
@@ -0,0 +1,54 @@
+From 0250abe3e304b348fa7ad719f035b0f4ed910365 Mon Sep 17 00:00:00 2001
+From: Axel Svensson <mail@axelsvensson.com>
+Date: Fri, 5 Sep 2025 08:57:08 +0200
+Subject: [PATCH 2/3] Help text formatting
+
+- Reflow to output max 79 columns.
+- Add a `=` to `--ignore-pid` for consistency.
+---
+ fatrace.c | 29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+diff --git a/fatrace.c b/fatrace.c
+index e683535..836c431 100644
+--- a/fatrace.c
++++ b/fatrace.c
+@@ -647,18 +647,23 @@ help (void)
+ puts ("Usage: fatrace [options...] \n"
+ "\n"
+ "Options:\n"
+-" -c, --current-mount\t\tOnly record events on partition/mount of current directory.\n"
+-" -o FILE, --output=FILE\tWrite events to a file instead of standard output.\n"
+-" -s SECONDS, --seconds=SECONDS\tStop after the given number of seconds.\n"
+-" -t, --timestamp\t\tAdd timestamp to events. Give twice for seconds since the epoch.\n"
+-" -u, --user\t\t\tAdd user ID and group ID to events.\n"
+-" -p PID, --ignore-pid PID\tIgnore events for this process ID. Can be specified multiple times.\n"
+-" -f TYPES, --filter=TYPES\tShow only the given event types; choose from C, R, O, W, +, D, < or >, e. g. --filter=OC.\n"
+-" -C COMM, --command=COMM\tShow only events for this command.\n"
+-" -j, --json\t\t\tWrite events in JSONL format.\n"
+-" -P, --parents\t\t\tInclude information about all parent processes.\n"
+-" -e, --exe\t\t\tAdd executable path to events.\n"
+-" -h, --help\t\t\tShow help.");
++" -c, --current-mount Only record events on partition/mount of\n"
++" current directory.\n"
++" -o FILE, --output=FILE Write events to a file instead of standard\n"
++" output.\n"
++" -s SECONDS, --seconds=SECONDS Stop after the given number of seconds.\n"
++" -t, --timestamp Add timestamp to events. Give twice for seconds\n"
++" since the epoch.\n"
++" -u, --user Add user ID and group ID to events.\n"
++" -p PID, --ignore-pid=PID Ignore events for this process ID. Can be\n"
++" specified multiple times.\n"
++" -f TYPES, --filter=TYPES Show only the given event types; choose from C,\n"
++" R, O, W, +, D, < or >, e. g. --filter=OC.\n"
++" -C COMM, --command=COMM Show only events for this command.\n"
++" -j, --json Write events in JSONL format.\n"
++" -P, --parents Include information about all parent processes.\n"
++" -e, --exe Add executable path to events.\n"
++" -h, --help Show help.");
+ }
+
+ /**
+--
+2.46.3
+
diff --git a/system/fatrace/patches/0003-Add-option-d-dir.patch b/system/fatrace/patches/0003-Add-option-d-dir.patch
new file mode 100644
index 0000000000..6a251555ba
--- /dev/null
+++ b/system/fatrace/patches/0003-Add-option-d-dir.patch
@@ -0,0 +1,320 @@
+From 21d7e40b2ccc2a3209341264bae97cc0a64cc068 Mon Sep 17 00:00:00 2001
+From: Axel Svensson <mail@axelsvensson.com>
+Date: Sun, 29 Jun 2025 17:30:53 +0200
+Subject: [PATCH 3/3] Add option -d,--dir
+
+Fixes #48
+---
+ fatrace.8 | 27 ++++++++++++-
+ fatrace.c | 50 ++++++++++++++++++++++-
+ tests/test.py | 107 ++++++++++++++++++++++++++++++++++++++++++++------
+ 3 files changed, 168 insertions(+), 16 deletions(-)
+
+diff --git a/fatrace.8 b/fatrace.8
+index 7117ee2..aa355b1 100644
+--- a/fatrace.8
++++ b/fatrace.8
+@@ -1,4 +1,4 @@
+-.TH fatrace 8 "August 20, 2020" "Martin Pitt"
++.TH fatrace 8 "September 5, 2025" "Martin Pitt"
+
+ .SH NAME
+
+@@ -10,6 +10,10 @@ fatrace \- report system wide file access events
+ [
+ .I OPTIONS
+ ]
++[
++--
++]
++[ \fIDIR\fR... ]
+
+ .SH DESCRIPTION
+
+@@ -212,6 +216,27 @@ Print information about all parent processes.
+ .B \-e\fR, \fB\-\-exe
+ Print executable path.
+
++.TP
++.B \-d \fIDIR\fR, \fB\-\-dir=\fIDIR\fR
++Show only events where the affected file is \fIdirectly\fR under this directory.
++Can be specified multiple times to include events from several directories.
++.IP
++This is \fInot\fR recursive. For example, \fB\-d /home/user\fR will show events
++for \fB/home/user/file\fR but not for \fB/home/user/subdir/file\fR.
++.IP
++\fIDIR\fRs can also be specified at the end of the command line, advisably
++preceded by the \fB\-\-\fR separator. As long as no directories will be created
++or moved under a subtree, it's possible to watch that subtree like so:
++.RS
++.IP "" 4
++fatrace -- $(find /path/to/subtree -type d)
++.RE
++.IP
++The attachment is to a directory inode, not the path. For example, this means
++that 1) If you move a watched directory while fatrace runs, you may receive
++events for a path that is not listed on the command line; 2) If you delete and
++recreate a watched directory you will no longer receive events.
++
+ .TP
+ .B \-h \fR, \fB\-\-help
+ Print help and exit.
+diff --git a/fatrace.c b/fatrace.c
+index 836c431..1c9042d 100644
+--- a/fatrace.c
++++ b/fatrace.c
+@@ -48,6 +48,9 @@
+
+ #define BUFSIZE 256*1024
+
++/* Likely to be less than /proc/sys/fs/fanotify/max_user_marks */
++#define MAX_DIRS 4096
++
+ /* https://man7.org/linux/man-pages/man5/proc_pid_comm.5.html ; not defined in any include file */
+ #ifndef TASK_COMM_LEN
+ #define TASK_COMM_LEN 16
+@@ -73,6 +76,8 @@ static char* option_comm = NULL;
+ static bool option_json = false;
+ static bool option_parents = false;
+ static bool option_exe = false;
++static const char *option_dirs[MAX_DIRS];
++static unsigned int option_dirs_len = 0;
+
+ /* --time alarm sets this to 0 */
+ static volatile int running = 1;
+@@ -594,6 +599,26 @@ do_mark (int fan_fd, const char *dir, bool fatal)
+ static void
+ setup_fanotify (int fan_fd)
+ {
++ if (option_dirs_len > 0) {
++ mark_mode = FAN_MARK_ADD;
++ char resolved[PATH_MAX];
++ struct stat st;
++ for (unsigned i = 0; i < option_dirs_len; i++) {
++ if (realpath(option_dirs[i], resolved) &&
++ stat(resolved, &st) == 0) {
++ if (S_ISDIR(st.st_mode))
++ do_mark (fan_fd, resolved, false);
++ else
++ errx(EXIT_FAILURE,
++ "Not a directory: %s", option_dirs[i]);
++ }
++ else
++ err(EXIT_FAILURE,
++ "Cannot resolve directory: %s", option_dirs[i]);
++ }
++ return;
++ }
++
+ FILE* mounts;
+ struct mntent* mount;
+
+@@ -644,7 +669,7 @@ setup_fanotify (int fan_fd)
+ static void
+ help (void)
+ {
+- puts ("Usage: fatrace [options...] \n"
++ puts ("Usage: fatrace [options...] [--] [DIR...]\n"
+ "\n"
+ "Options:\n"
+ " -c, --current-mount Only record events on partition/mount of\n"
+@@ -663,6 +688,10 @@ help (void)
+ " -j, --json Write events in JSONL format.\n"
+ " -P, --parents Include information about all parent processes.\n"
+ " -e, --exe Add executable path to events.\n"
++" -d DIR, --dir=DIR Show only events on files directly under this\n"
++" directory. NOT recursive. Can be specified\n"
++" multiple times. DIRs can also be specified at\n"
++" the end of the command line.\n"
+ " -h, --help Show help.");
+ }
+
+@@ -691,12 +720,13 @@ parse_args (int argc, char** argv)
+ {"json", no_argument, 0, 'j'},
+ {"parents", no_argument, 0, 'P'},
+ {"exe", no_argument, 0, 'e'},
++ {"dir", required_argument, 0, 'd'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0 }
+ };
+
+ while (1) {
+- c = getopt_long (argc, argv, "C:co:s:tup:f:jPeh", long_options, NULL);
++ c = getopt_long (argc, argv, "C:co:s:tup:f:jPed:h", long_options, NULL);
+
+ if (c == -1)
+ break;
+@@ -801,6 +831,13 @@ parse_args (int argc, char** argv)
+ option_exe = true;
+ break;
+
++ case 'd':
++ if (option_dirs_len >= MAX_DIRS)
++ errx (EXIT_FAILURE, "Error: Too many --dir arguments"
++ " (maximum is %d).", MAX_DIRS);
++ option_dirs[option_dirs_len++] = optarg;
++ break;
++
+ case 'h':
+ help ();
+ exit (EXIT_SUCCESS);
+@@ -813,6 +850,15 @@ parse_args (int argc, char** argv)
+ errx (EXIT_FAILURE, "Internal error: unexpected option '%c'", c);
+ }
+ }
++ for (int i = optind; i < argc; i++) {
++ if (option_dirs_len >= MAX_DIRS)
++ errx (EXIT_FAILURE, "Error: Too many --dir and DIR arguments"
++ " (maximum is %d).", MAX_DIRS);
++ option_dirs[option_dirs_len++] = argv[i];
++ }
++ if (option_current_mount && option_dirs_len > 0)
++ errx (EXIT_FAILURE,
++ "Error: -c,--current-mount and -d,--dir are mutually exclusive.");
+ }
+
+ static void
+diff --git a/tests/test.py b/tests/test.py
+index 0dd904a..f86c0e1 100644
+--- a/tests/test.py
++++ b/tests/test.py
+@@ -72,18 +72,30 @@ class FatraceRunner:
+ self.log_content = f.read()
+ self.log_dir.cleanup()
+
+- def assert_log(self, pattern: str) -> None:
++ def has_log(self, pattern: str) -> bool:
+ """Check if a regex pattern exists in the log content."""
+
+ assert self.log_content, "Need to call run() first"
+
+- if not re.search(pattern, self.log_content, re.MULTILINE):
+- raise AssertionError(f"""Pattern not found in log: {pattern}
+----- Log content ----
+-{self.log_content}
+------------------""")
++ return bool(re.search(pattern, self.log_content, re.MULTILINE))
+
+- def assert_json(self, condition_func: Callable[[dict], bool]) -> None:
++ def assert_log(self, pattern: str) -> None:
++ if self.has_log(pattern):
++ return
++ raise AssertionError(f"Pattern not found in log: {pattern}\n"
++ "---- Log content ----\n"
++ f"{self.log_content}\n"
++ "-----------------")
++
++ def assert_not_log(self, pattern: str) -> None:
++ if not self.has_log(pattern):
++ return
++ raise AssertionError(f"Pattern found in log: {pattern}\n"
++ "---- Log content ----\n"
++ f"{self.log_content}\n"
++ "-----------------")
++
++ def has_json(self, condition_func: Callable[[dict], bool]) -> bool:
+ """Check if any JSON line matches the condition function."""
+
+ assert self.log_content, "Need to call run() first"
+@@ -94,16 +106,27 @@ class FatraceRunner:
+ entry = json.loads(line)
+ try:
+ if condition_func(entry):
+- return
++ return True
+ except KeyError:
+ # Ignore entries that do not match the expected structure
+ pass
++ return False
+
+- raise AssertionError(f"""No JSON entry matched condition
+----- Log content ----
+-{self.log_content}
+------------------""")
+-
++ def assert_json(self, condition_func: Callable[[dict], bool]) -> None:
++ if self.has_json(condition_func):
++ return
++ raise AssertionError("No JSON entry matched condition\n"
++ "---- Log content ----\n"
++ f"{self.log_content}\n"
++ "-----------------")
++
++ def assert_not_json(self, condition_func: Callable[[dict], bool]) -> None:
++ if not self.has_json(condition_func):
++ return
++ raise AssertionError("At least one JSON entry matched condition\n"
++ "---- Log content ----\n"
++ f"{self.log_content}\n"
++ "-----------------")
+
+ class FatraceTests(unittest.TestCase):
+ def setUp(self):
+@@ -574,6 +597,64 @@ with open("{python_pid_file}", "w") as f: f.write(f"{{os.getpid()}}\\n")
+ "path" not in e
+ ))
+
++ def test_dir(self):
++ yes1 = str(self.tmp_path / "yes-1")
++ yes2 = str(self.tmp_path / "yes-2")
++ no1 = str(self.tmp_path / "no-1")
++
++ exe(["mkdir", yes1])
++ exe(["mkdir", yes2])
++ exe(["mkdir", no1])
++
++ f = FatraceRunner(["-s", "3", "-d", yes1, f"--dir={yes2}"])
++ f_json = FatraceRunner(["-s", "3", "--json", "--", yes1, yes2])
++
++ slow_exe(["mkdir", f"{yes1}/subA"])
++ slow_exe(["mkdir", f"{no1}/subB"])
++
++ slow_exe(["touch", f"{yes1}/yesC"])
++ slow_exe(["touch", f"{yes1}/subA/noD"])
++ slow_exe(["touch", f"{yes2}/yesE"])
++ slow_exe(["touch", f"{no1}/noF"])
++ slow_exe(["touch", f"{no1}/subB/noG"])
++
++ slow_exe(["mv", yes1, yes2])
++ new_yes1 = str(self.tmp_path / "yes-2" / "yes-1")
++ slow_exe(["mv", no1, yes2])
++ new_no1 = str(self.tmp_path / "yes-2" / "no-1")
++
++ slow_exe(["touch", f"{new_yes1}/yesH"])
++ slow_exe(["touch", f"{new_yes1}/subA/noI"])
++ slow_exe(["touch", f"{new_no1}/noJ"])
++ slow_exe(["touch", f"{new_no1}/subB/noK"])
++
++ f.finish()
++ f_json.finish()
++
++ f.assert_log (rf"^mkdir\([0-9]*\): \+ +{re.escape(yes1)}")
++ f.assert_not_log(rf"^mkdir\([0-9]*\): \+ +{re.escape(no1)}")
++ f.assert_log (rf"^touch\([0-9]*\): C?WO? +{re.escape(yes1)}/yesC")
++ f.assert_not_log(rf"^touch\([0-9]*\): C?WO? +{re.escape(yes1)}/subA/noD")
++ f.assert_log (rf"^touch\([0-9]*\): C?WO? +{re.escape(yes2)}/yesE")
++ f.assert_not_log(rf"^touch\([0-9]*\): C?WO? +{re.escape(no1)}/noF")
++ f.assert_not_log(rf"^touch\([0-9]*\): C?WO? +{re.escape(no1)}/subB/noG")
++ f.assert_log (rf"^touch\([0-9]*\): C?WO? +{re.escape(new_yes1)}/yesH")
++ f.assert_not_log(rf"^touch\([0-9]*\): C?WO? +{re.escape(new_yes1)}/subA/noI")
++ f.assert_not_log(rf"^touch\([0-9]*\): C?WO? +{re.escape(new_no1)}/noJ")
++ f.assert_not_log(rf"^touch\([0-9]*\): C?WO? +{re.escape(new_no1)}/subB/noK")
++
++ f_json.assert_json (lambda e: e["comm"] == "mkdir" and e["types"] == "+" and e["path"] == yes1)
++ f_json.assert_not_json(lambda e: e["comm"] == "mkdir" and e["types"] == "+" and e["path"] == no1)
++ f_json.assert_json (lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{yes1}/yesC")
++ f_json.assert_not_json(lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{yes1}/subA/noD")
++ f_json.assert_json (lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{yes2}/yesE")
++ f_json.assert_not_json(lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{no1}/noF")
++ f_json.assert_not_json(lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{no1}/subB/noG")
++ f_json.assert_json (lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{new_yes1}/yesH")
++ f_json.assert_not_json(lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{new_yes1}/subA/noI")
++ f_json.assert_not_json(lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{new_no1}/noJ")
++ f_json.assert_not_json(lambda e: e["comm"] == "touch" and "W" in e["types"] and e["path"] == f"{new_no1}/subB/noK")
++
+ @unittest.skipIf("container" in os.environ, "Not supported in container environment")
+ @unittest.skipIf(os.path.exists("/sysroot/ostree"), "Test does not work on OSTree")
+ @unittest.skipIf(root_is_btrfs, "FANOTIFY does not work on btrfs, https://github.com/martinpitt/fatrace/issues/3")
+--
+2.46.3
+
diff --git a/system/fatrace/slack-desc b/system/fatrace/slack-desc
index f9527c7825..54dc4d30f8 100644
--- a/system/fatrace/slack-desc
+++ b/system/fatrace/slack-desc
@@ -12,7 +12,7 @@ fatrace: fatrace reports file access events from all running processes.
fatrace: Its main purpose is to find processes which keep waking up the disk
fatrace: unnecessarily and thus prevent some power saving.
fatrace:
-fatrace: Homepage: https://launchpad.net/fatrace
+fatrace:
fatrace:
fatrace:
fatrace: