Luigit
repositories / termux-janitor

termux-janitor

Interactive cleanup assistant for Termux: transparent, safe, confirmed disk reclamation.

owned by admin

spec/experiments/run_log_flush.md

Raw
Rendered preview

Run-log flush capability experiment

Question

Does the target Termux private temporary filesystem accept the run-log open, append, file-flush, and parent-directory-flush sequence required by PRODUCT.md?

Hypothesis

Opening a new log with O_APPEND | O_NOFOLLOW | O_CLOEXEC, writing intent and result records, flushing each with fdatasync, and flushing the parent directory with fsync all succeed. fdatasync(-1) fails with EBADF as a negative control.

Any failed positive operation or successful invalid-descriptor control falsifies the hypothesis.

Environment

  • Date: 2026-09-14
  • Kernel: Linux 6.1.176 Android 14, AArch64
  • Compiler: Clang 21.1.8 targeting aarch64-unknown-linux-android24
  • Tracer: strace 7.2
  • Fixture: a fresh directory below Termux $TMPDIR, removed after the probe

Method

A C17 probe performed this sequence:

  1. Open the fixture directory with O_DIRECTORY | O_CLOEXEC.
  2. Create run.log with O_APPEND | O_NOFOLLOW | O_CLOEXEC and mode 0600.
  3. Write intent\n and call fdatasync on the file.
  4. Call fsync on the parent directory.
  5. Write result\n and call fdatasync on the file.
  6. Require fdatasync(-1) to fail with EBADF.
  7. Reopen the file with O_NOFOLLOW and verify the exact contents.

The probe compiled with:

clang -std=c17 -Wall -Wextra -Werror -O2 -o probe probe.c

The syscall trace used:

strace -e trace=openat,write,fdatasync,fsync,close,read ./probe <fixture>

An initial zig cc attempt failed before running the probe because this Termux Zig invocation did not find asm/errno.h through its selected headers. Clang targets the installed Android API directly and compiled the same source without warnings. This tooling failure does not bear on filesystem capability.

Observations

The probe exited successfully and reported:

open_no_follow_append=yes
intent_fdatasync=yes
parent_fsync=yes
result_fdatasync=yes
invalid_fd_control=EBADF
content=intent,result

The independent syscall trace recorded the required order:

openat(3, "run.log", O_WRONLY|O_CREAT|O_APPEND|O_NOFOLLOW|O_CLOEXEC, 0600) = 4
write(4, "intent\n", 7) = 7
fdatasync(4) = 0
fsync(3) = 0
write(4, "result\n", 7) = 7
fdatasync(4) = 0
fdatasync(-1) = -1 EBADF (Bad file descriptor)
openat(3, "run.log", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = 4

All temporary source, binary, log, and trace files were removed after collecting the observations.

Conclusion

The required open and flush operations are supported on the tested Termux private temporary filesystem. The result supports capable-platform testing of the specified run-log sequence.

A successful fdatasync or fsync reports kernel acceptance only. This experiment does not prove survival across power loss, dishonest storage firmware, filesystem bugs, other filesystems, or every supported Android version. Runtime failure must still block mutation admission or pause execution as specified.

# Run-log flush capability experiment

## Question

Does the target Termux private temporary filesystem accept the run-log open, append, file-flush, and
parent-directory-flush sequence required by [`PRODUCT.md`](../PRODUCT.md#113-failure-behavior)?

## Hypothesis

Opening a new log with `O_APPEND | O_NOFOLLOW | O_CLOEXEC`, writing intent and result records,
flushing each with `fdatasync`, and flushing the parent directory with `fsync` all succeed.
`fdatasync(-1)` fails with `EBADF` as a negative control.

Any failed positive operation or successful invalid-descriptor control falsifies the hypothesis.

## Environment

- Date: 2026-09-14
- Kernel: Linux 6.1.176 Android 14, AArch64
- Compiler: Clang 21.1.8 targeting `aarch64-unknown-linux-android24`
- Tracer: strace 7.2
- Fixture: a fresh directory below Termux `$TMPDIR`, removed after the probe

## Method

A C17 probe performed this sequence:

1. Open the fixture directory with `O_DIRECTORY | O_CLOEXEC`.
2. Create `run.log` with `O_APPEND | O_NOFOLLOW | O_CLOEXEC` and mode `0600`.
3. Write `intent\n` and call `fdatasync` on the file.
4. Call `fsync` on the parent directory.
5. Write `result\n` and call `fdatasync` on the file.
6. Require `fdatasync(-1)` to fail with `EBADF`.
7. Reopen the file with `O_NOFOLLOW` and verify the exact contents.

The probe compiled with:

```text
clang -std=c17 -Wall -Wextra -Werror -O2 -o probe probe.c
```

The syscall trace used:

```text
strace -e trace=openat,write,fdatasync,fsync,close,read ./probe <fixture>
```

An initial `zig cc` attempt failed before running the probe because this Termux Zig invocation did not
find `asm/errno.h` through its selected headers. Clang targets the installed Android API directly and
compiled the same source without warnings. This tooling failure does not bear on filesystem
capability.

## Observations

The probe exited successfully and reported:

```text
open_no_follow_append=yes
intent_fdatasync=yes
parent_fsync=yes
result_fdatasync=yes
invalid_fd_control=EBADF
content=intent,result
```

The independent syscall trace recorded the required order:

```text
openat(3, "run.log", O_WRONLY|O_CREAT|O_APPEND|O_NOFOLLOW|O_CLOEXEC, 0600) = 4
write(4, "intent\n", 7) = 7
fdatasync(4) = 0
fsync(3) = 0
write(4, "result\n", 7) = 7
fdatasync(4) = 0
fdatasync(-1) = -1 EBADF (Bad file descriptor)
openat(3, "run.log", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = 4
```

All temporary source, binary, log, and trace files were removed after collecting the observations.

## Conclusion

**The required open and flush operations are supported on the tested Termux private temporary
filesystem.** The result supports capable-platform testing of the specified run-log sequence.

A successful `fdatasync` or `fsync` reports kernel acceptance only. This experiment does not prove
survival across power loss, dishonest storage firmware, filesystem bugs, other filesystems, or every
supported Android version. Runtime failure must still block mutation admission or pause execution as
specified.