Repository: metalbear-co/mirrord (language: rust)

Issue:
statfs is always remote
Code
```java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileReader {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: java FileReader <file_path>");
            System.exit(1);
        }

        String filePath = args[0];

        try {
            Path path = Paths.get(filePath);
            String content = Files.readString(path);
            System.out.println("File contents:");
            System.out.println("-------------");
            System.out.println(content);

        } catch (IOException e) {
            System.err.println("Error reading file: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
    }
}
```
running with
```
mirrord exec -- java FileReader.java /etc/hosts
```

shows in internal proxy (when enabled) that it tries to access remote `/System/...` on macOS
Upon checking the code, I saw no any check if we should ignore the path...


Discussion / hints:
<p><a href="https://linear.app/metalbear/issue/MBE-718/statfs-is-always-remote">MBE-718 statfs is always remote</a></p>
As part of solving that, we should add tests that cover it.

Fix patch:
diff --git a/changelog.d/3082.fixed.md b/changelog.d/3082.fixed.md
new file mode 100644
index 00000000000..8d887470477
--- /dev/null
+++ b/changelog.d/3082.fixed.md
@@ -0,0 +1,1 @@
+Respect ignored paths and path mapping in statfs hook.
diff --git a/mirrord/layer/src/file/ops.rs b/mirrord/layer/src/file/ops.rs
index 79dc3769ef0..d894fcd5e45 100644
--- a/mirrord/layer/src/file/ops.rs
+++ b/mirrord/layer/src/file/ops.rs
@@ -746,6 +746,12 @@ pub(crate) fn xstatfs(fd: RawFd) -> Detour<XstatFsResponseV2> {
 pub(crate) fn statfs(path: Detour<PathBuf>) -> Detour<XstatFsResponseV2> {
     let path = path?;
 
+    check_relative_paths!(path);
+
+    let path = remap_path!(path);
+
+    ensure_not_ignored!(path, false);
+
     // intproxy downgrades to old version if new one is not supported by agent, and converts
     // old version responses to V2 responses.
     let statfs = StatFsRequestV2 { path };


Test patch:
diff --git a/mirrord/layer/tests/apps/fileops/go/main.go b/mirrord/layer/tests/apps/fileops/go/main.go
index 69db336fb3e..3f7152c2876 100644
--- a/mirrord/layer/tests/apps/fileops/go/main.go
+++ b/mirrord/layer/tests/apps/fileops/go/main.go
@@ -20,6 +20,19 @@ func main() {
 		panic(err)
 	}
 
+    // Call statfs on a relative path so that the test can verify it's bypassed.
+	err = syscall.Statfs(".", &statfs)
+	if err != nil {
+		panic(err)
+	}
+
+    // Call statfs on the root path so that the test can verify it's bypassed (the root path is one of the paths)
+    // that are read locally by default.
+	err = syscall.Statfs("/", &statfs)
+	if err != nil {
+		panic(err)
+	}
+
 	err = syscall.Fstatfs(fd, &statfs)
 	if err != nil {
 		panic(err)
diff --git a/tests/go-e2e-statfs/main.go b/tests/go-e2e-statfs/main.go
index 2b42670cec7..878b02d1b18 100644
--- a/tests/go-e2e-statfs/main.go
+++ b/tests/go-e2e-statfs/main.go
@@ -10,9 +10,9 @@ import (
 )
 
 func main() {
-	rootPath := "/"
+	testPath := "/app/test.txt"
 	var statfs syscall.Statfs_t
-	err := syscall.Statfs(rootPath, &statfs)
+	err := syscall.Statfs(testPath, &statfs)
 	if err != nil {
 		fmt.Println("Error:", err)
 		return