Skip to content

hamma_scrub.select_target_drive: Windows artifact dirs defeat the most-recent-hour heuristic, can select a read-only drive #93

Description

@pbitzer

Summary

scripts/hamma_scrub.py::select_target_drive picks the recovery target as "the drive containing the most recent hourly directory", but the heuristic is defeated on any drive prepared under Windows, because it does not exclude the Windows artifact directories.

The bug

for entry in os.listdir(drive):
    if entry == "compressed":
        continue
    full = os.path.join(drive, entry)
    if os.path.isdir(full) and entry > most_recent:
        most_recent = entry

Only compressed is excluded. Both $RECYCLE.BIN and System Volume Information are directories and both sort above any 2026-… hourly directory in ASCII (S = 0x53 beats 2 = 0x32).

So every Windows-prepared drive yields the same sort key:

drive sort key
DATA80 System Volume Information
DATA81 System Volume Information

The keys tie. Python's sort is stable, so sorted(glob.glob(pattern)) order decides — i.e. the alphabetically first drive by name, not the one with the most recent data. The hour-directory heuristic is completely inert on such drives.

Observed consequence

On mjolnir54 this handed recovery to DATA80 — which was mounted read-only — while DATA81 was the writable drive. Recovery then failed on every trigger:

Recovery: 1417 attempted, 0 succeeded, 1417 failed
FAILED: ags2026-08-06_00-08-16-939.bin trigger #34 —
  [Errno 30] Read-only file system: '/media/pi/DATA80/.tmp_recover_r9bp_ys8.bin'

See sensor-log #110 for the full incident.

Suggested fix

Exclude the Windows artifacts alongside compressed, and — more robustly — only consider entries that actually match the hourly-directory shape rather than blacklisting known-bad names:

HOURLY_DIR_RE = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}$")
...
if os.path.isdir(full) and HOURLY_DIR_RE.match(entry) and entry > most_recent:

A whitelist is preferable here: the blacklist has already been wrong twice (compressed was added reactively, the Windows dirs were missed), and any future stray directory re-breaks it.

Worth deciding separately what should happen when no drive has any hourly directory — currently they all tie at "" and the choice again falls to glob order. On a freshly replaced drive that is exactly the situation.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions